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 "private/qdeclarativevme_p.h"
44 #include "private/qdeclarativecompiler_p.h"
45 #include "private/qdeclarativeboundsignal_p.h"
46 #include "private/qdeclarativestringconverters_p.h"
47 #include "private/qmetaobjectbuilder_p.h"
48 #include "private/qfastmetabuilder_p.h"
49 #include "private/qdeclarativedata_p.h"
50 #include "qdeclarative.h"
51 #include "private/qdeclarativecustomparser_p.h"
52 #include "qdeclarativeengine.h"
53 #include "qdeclarativecontext.h"
54 #include "qdeclarativecomponent.h"
55 #include "private/qdeclarativebinding_p.h"
56 #include "private/qdeclarativeengine_p.h"
57 #include "private/qdeclarativecomponent_p.h"
58 #include "private/qdeclarativevmemetaobject_p.h"
59 #include "private/qdeclarativebinding_p_p.h"
60 #include "private/qdeclarativecontext_p.h"
61 #include "private/qdeclarativev4bindings_p.h"
62 #include "private/qv8bindings_p.h"
63 #include "private/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)
99 if (start == -1) start = 0;
102 initState.context = ctxt;
103 initState.compiledData = comp;
104 initState.instructionStream = comp->bytecode.constData() + start;
105 states.push(initState);
107 typedef QDeclarativeInstruction I;
108 I *i = (I *)initState.instructionStream;
110 Q_ASSERT(comp->instructionType(i) == I::Init);
112 objects.allocate(i->init.objectStackSize);
113 lists.allocate(i->init.listStackSize);
114 bindValues.allocate(i->init.bindingsSize);
115 parserStatus.allocate(i->init.parserStatusSize);
118 engine = ctxt->engine;
121 bool QDeclarativeVME::initDeferred(QObject *object)
123 QDeclarativeData *data = QDeclarativeData::get(object);
125 if (!data || !data->context || !data->deferredComponent)
128 QDeclarativeContextData *ctxt = data->context;
129 QDeclarativeCompiledData *comp = data->deferredComponent;
130 int start = data->deferredIdx;
133 initState.context = ctxt;
134 initState.compiledData = comp;
135 initState.instructionStream = comp->bytecode.constData() + start;
136 states.push(initState);
138 typedef QDeclarativeInstruction I;
139 I *i = (I *)initState.instructionStream;
141 Q_ASSERT(comp->instructionType(i) == I::DeferInit);
143 objects.allocate(i->deferInit.objectStackSize);
144 lists.allocate(i->deferInit.listStackSize);
145 bindValues.allocate(i->deferInit.bindingsSize);
146 parserStatus.allocate(i->deferInit.parserStatusSize);
148 objects.push(object);
151 engine = ctxt->engine;
157 struct ActiveVMERestorer
159 ActiveVMERestorer(QDeclarativeVME *me, QDeclarativeEnginePrivate *ep)
160 : ep(ep), oldVME(ep->activeVME) { ep->activeVME = me; }
161 ~ActiveVMERestorer() { ep->activeVME = oldVME; }
163 QDeclarativeEnginePrivate *ep;
164 QDeclarativeVME *oldVME;
168 QObject *QDeclarativeVME::execute(QList<QDeclarativeError> *errors, const Interrupt &interrupt)
170 Q_ASSERT(states.count() >= 1);
172 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(states.at(0).context->engine);
174 ActiveVMERestorer restore(this, ep);
176 QObject *rv = run(errors, interrupt);
181 inline bool fastHasBinding(QObject *o, int index)
183 QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
185 return ddata && (ddata->bindingBitsSize > index) &&
186 (ddata->bindingBits[index / 32] & (1 << (index % 32)));
189 static void removeBindingOnProperty(QObject *o, int index)
191 QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
192 if (binding) binding->destroy();
195 // XXX we probably need some form of "work count" here to prevent us checking this
196 // for every instruction.
197 #define QML_BEGIN_INSTR_COMMON(I) { \
198 if (interrupt.shouldInterrupt()) return 0; \
199 const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(*genericInstr); \
200 INSTRUCTIONSTREAM += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \
203 #ifdef QML_THREADED_VME_INTERPRETER
204 # define QML_BEGIN_INSTR(I) op_##I: \
205 QML_BEGIN_INSTR_COMMON(I)
207 # define QML_NEXT_INSTR(I) { \
208 genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
209 goto *genericInstr->common.code; \
212 # define QML_END_INSTR(I) } \
213 genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
214 goto *genericInstr->common.code;
217 # define QML_BEGIN_INSTR(I) \
218 case QDeclarativeInstruction::I: \
219 QML_BEGIN_INSTR_COMMON(I)
221 # define QML_NEXT_INSTR(I) break;
222 # define QML_END_INSTR(I) } break;
225 #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
227 QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
228 const Interrupt &interrupt
229 #ifdef QML_THREADED_VME_INTERPRETER
230 , void ***storeJumpTable
234 #ifdef QML_THREADED_VME_INTERPRETER
235 if (storeJumpTable) {
236 #define QML_INSTR_ADDR(I, FMT) &&op_##I,
237 static void *jumpTable[] = {
238 FOR_EACH_QML_INSTR(QML_INSTR_ADDR)
240 #undef QML_INSTR_ADDR
241 *storeJumpTable = jumpTable;
245 Q_ASSERT(errors->isEmpty());
246 Q_ASSERT(states.count() >= 1);
248 QDeclarativeEngine *engine = states.at(0).context->engine;
249 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
251 int status = -1; // needed for dbus
252 QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
253 QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
255 #define COMP states.top().compiledData
256 #define CTXT states.top().context
257 #define INSTRUCTIONSTREAM states.top().instructionStream
258 #define BINDINGSKIPLIST states.top().bindingSkipList
260 #define TYPES COMP->types
261 #define PRIMITIVES COMP->primitives
262 #define DATAS COMP->datas
263 #define PROPERTYCACHES COMP->propertyCaches
264 #define SCRIPTS COMP->scripts
265 #define URLS COMP->urls
267 #ifdef QML_THREADED_VME_INTERPRETER
268 const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM);
269 goto *genericInstr->common.code;
272 const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM);
274 switch (genericInstr->common.instructionType) {
276 QML_BEGIN_INSTR(Init)
277 // Ensure that the compiled data has been initialized
278 if (!COMP->isInitialized()) COMP->initialize(engine);
280 QDeclarativeContextData *parentCtxt = CTXT;
281 CTXT = new QDeclarativeContextData;
282 CTXT->isInternal = true;
283 CTXT->url = COMP->url;
284 CTXT->imports = COMP->importCache;
285 CTXT->imports->addref();
286 CTXT->setParent(parentCtxt);
287 if (instr.contextCache != -1)
288 CTXT->setIdPropertyData(COMP->contextCaches.at(instr.contextCache));
289 if (instr.compiledBinding != -1) {
290 const char *v4data = DATAS.at(instr.compiledBinding).constData();
291 CTXT->v4bindings = new QDeclarativeV4Bindings(v4data, CTXT, COMP);
293 if (states.count() == 1) {
295 rootContext->activeVME = this;
299 QML_BEGIN_INSTR(DeferInit)
300 QML_END_INSTR(DeferInit)
302 QML_BEGIN_INSTR(Done)
305 if (states.isEmpty())
309 QML_BEGIN_INSTR(CreateQMLObject)
310 const QDeclarativeCompiledData::TypeReference &type = TYPES.at(instr.type);
311 Q_ASSERT(type.component);
313 states.push(State());
315 State *cState = &states[states.count() - 2];
316 State *nState = &states[states.count() - 1];
318 nState->context = cState->context;
319 nState->compiledData = type.component;
320 nState->instructionStream = type.component->bytecode.constData();
322 if (instr.bindingBits != -1) {
323 const QByteArray &bits = cState->compiledData->datas.at(instr.bindingBits);
324 nState->bindingSkipList = QBitField((const quint32*)bits.constData(),
328 nState->bindingSkipList = nState->bindingSkipList.united(cState->bindingSkipList);
330 // As the state in the state stack changed, execution will continue in the new program.
331 QML_END_INSTR(CreateQMLObject)
333 QML_BEGIN_INSTR(CompleteQMLObject)
334 QObject *o = objects.top();
336 QDeclarativeData *ddata = QDeclarativeData::get(o);
340 if (ddata->context) {
341 Q_ASSERT(ddata->context != CTXT);
342 Q_ASSERT(ddata->outerContext);
343 Q_ASSERT(ddata->outerContext != CTXT);
344 QDeclarativeContextData *c = ddata->context;
345 while (c->linkedContext) c = c->linkedContext;
346 c->linkedContext = CTXT;
351 ddata->ownContext = true;
352 } else if (!ddata->context) {
356 ddata->setImplicitDestructible();
357 ddata->outerContext = CTXT;
358 ddata->lineNumber = instr.line;
359 ddata->columnNumber = instr.column;
360 QML_END_INSTR(CompleteQMLObject)
362 QML_BEGIN_INSTR(CreateCppObject)
363 const QDeclarativeCompiledData::TypeReference &type = TYPES.at(instr.type);
368 type.type->create(&o, &memory, sizeof(QDeclarativeData));
369 QDeclarativeData *ddata = new (memory) QDeclarativeData;
370 ddata->ownMemory = false;
371 QObjectPrivate::get(o)->declarativeData = ddata;
373 if (type.typePropertyCache && !ddata->propertyCache) {
374 ddata->propertyCache = type.typePropertyCache;
375 ddata->propertyCache->addref();
379 VME_EXCEPTION(tr("Unable to create object of type %1").arg(type.className), instr.line);
382 if (ddata->context) {
383 Q_ASSERT(ddata->context != CTXT);
384 Q_ASSERT(ddata->outerContext);
385 Q_ASSERT(ddata->outerContext != CTXT);
386 QDeclarativeContextData *c = ddata->context;
387 while (c->linkedContext) c = c->linkedContext;
388 c->linkedContext = CTXT;
393 ddata->ownContext = true;
394 } else if (!ddata->context) {
398 ddata->setImplicitDestructible();
399 ddata->outerContext = CTXT;
400 ddata->lineNumber = instr.line;
401 ddata->columnNumber = instr.column;
403 if (instr.data != -1) {
404 QDeclarativeCustomParser *customParser =
405 TYPES.at(instr.type).type->customParser();
406 customParser->setCustomData(o, DATAS.at(instr.data));
408 if (!objects.isEmpty()) {
409 QObject *parent = objects.top();
410 #if 0 // ### refactor
411 if (o->isWidgetType() && parent->isWidgetType())
412 static_cast<QWidget*>(o)->setParent(static_cast<QWidget*>(parent));
415 QDeclarative_setParent_noEvent(o, parent);
418 QML_END_INSTR(CreateCppObject)
420 QML_BEGIN_INSTR(CreateSimpleObject)
421 QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));
422 ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
425 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
426 const QDeclarativeCompiledData::TypeReference &ref = TYPES.at(instr.type);
427 if (!ddata->propertyCache && ref.typePropertyCache) {
428 ddata->propertyCache = ref.typePropertyCache;
429 ddata->propertyCache->addref();
431 ddata->lineNumber = instr.line;
432 ddata->columnNumber = instr.column;
434 QObjectPrivate::get(o)->declarativeData = ddata;
435 ddata->context = ddata->outerContext = CTXT;
436 ddata->nextContextObject = CTXT->contextObjects;
437 if (ddata->nextContextObject)
438 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
439 ddata->prevContextObject = &CTXT->contextObjects;
440 CTXT->contextObjects = ddata;
442 QObject *parent = objects.top();
443 QDeclarative_setParent_noEvent(o, parent);
446 QML_END_INSTR(CreateSimpleObject)
448 QML_BEGIN_INSTR(SetId)
449 QObject *target = objects.top();
450 CTXT->setIdProperty(instr.index, target);
453 QML_BEGIN_INSTR(SetDefault)
454 CTXT->contextObject = objects.top();
455 QML_END_INSTR(SetDefault)
457 QML_BEGIN_INSTR(CreateComponent)
458 QDeclarativeComponent *qcomp =
459 new QDeclarativeComponent(CTXT->engine, COMP, INSTRUCTIONSTREAM - COMP->bytecode.constData(),
460 objects.isEmpty() ? 0 : objects.top());
462 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
465 CTXT->addObject(qcomp);
468 ddata->ownContext = true;
470 ddata->setImplicitDestructible();
471 ddata->outerContext = CTXT;
472 ddata->lineNumber = instr.line;
473 ddata->columnNumber = instr.column;
475 QDeclarativeComponentPrivate::get(qcomp)->creationContext = CTXT;
478 INSTRUCTIONSTREAM += instr.count;
479 QML_END_INSTR(CreateComponent)
481 QML_BEGIN_INSTR(StoreMetaObject)
482 QObject *target = objects.top();
485 const QByteArray &metadata = DATAS.at(instr.data);
486 QFastMetaBuilder::fromData(&mo, 0, metadata);
488 const QDeclarativeVMEMetaData *data =
489 (const QDeclarativeVMEMetaData *)DATAS.at(instr.aliasData).constData();
491 (void)new QDeclarativeVMEMetaObject(target, &mo, data, COMP);
493 if (instr.propertyCache != -1) {
494 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
495 if (ddata->propertyCache) ddata->propertyCache->release();
496 ddata->propertyCache = PROPERTYCACHES.at(instr.propertyCache);
497 ddata->propertyCache->addref();
499 QML_END_INSTR(StoreMetaObject)
501 QML_BEGIN_INSTR(StoreVariant)
502 QObject *target = objects.top();
503 CLEAN_PROPERTY(target, instr.propertyIndex);
505 // XXX - can be more efficient
506 QVariant v = QDeclarativeStringConverters::variantFromString(PRIMITIVES.at(instr.value));
507 void *a[] = { &v, 0, &status, &flags };
508 QMetaObject::metacall(target, QMetaObject::WriteProperty,
509 instr.propertyIndex, a);
510 QML_END_INSTR(StoreVariant)
512 QML_BEGIN_INSTR(StoreVariantInteger)
513 QObject *target = objects.top();
514 CLEAN_PROPERTY(target, instr.propertyIndex);
516 QVariant v(instr.value);
517 void *a[] = { &v, 0, &status, &flags };
518 QMetaObject::metacall(target, QMetaObject::WriteProperty,
519 instr.propertyIndex, a);
520 QML_END_INSTR(StoreVariantInteger)
522 QML_BEGIN_INSTR(StoreVariantDouble)
523 QObject *target = objects.top();
524 CLEAN_PROPERTY(target, instr.propertyIndex);
526 QVariant v(instr.value);
527 void *a[] = { &v, 0, &status, &flags };
528 QMetaObject::metacall(target, QMetaObject::WriteProperty,
529 instr.propertyIndex, a);
530 QML_END_INSTR(StoreVariantDouble)
532 QML_BEGIN_INSTR(StoreVariantBool)
533 QObject *target = objects.top();
534 CLEAN_PROPERTY(target, instr.propertyIndex);
536 QVariant v(instr.value);
537 void *a[] = { &v, 0, &status, &flags };
538 QMetaObject::metacall(target, QMetaObject::WriteProperty,
539 instr.propertyIndex, a);
540 QML_END_INSTR(StoreVariantBool)
542 QML_BEGIN_INSTR(StoreString)
543 QObject *target = objects.top();
544 CLEAN_PROPERTY(target, instr.propertyIndex);
546 void *a[] = { (void *)&PRIMITIVES.at(instr.value), 0, &status, &flags };
547 QMetaObject::metacall(target, QMetaObject::WriteProperty,
548 instr.propertyIndex, a);
549 QML_END_INSTR(StoreString)
551 QML_BEGIN_INSTR(StoreByteArray)
552 QObject *target = objects.top();
553 void *a[] = { (void *)&DATAS.at(instr.value), 0, &status, &flags };
554 QMetaObject::metacall(target, QMetaObject::WriteProperty,
555 instr.propertyIndex, a);
556 QML_END_INSTR(StoreByteArray)
558 QML_BEGIN_INSTR(StoreUrl)
559 QObject *target = objects.top();
560 CLEAN_PROPERTY(target, instr.propertyIndex);
562 void *a[] = { (void *)&URLS.at(instr.value), 0, &status, &flags };
563 QMetaObject::metacall(target, QMetaObject::WriteProperty,
564 instr.propertyIndex, a);
565 QML_END_INSTR(StoreUrl)
567 QML_BEGIN_INSTR(StoreFloat)
568 QObject *target = objects.top();
569 CLEAN_PROPERTY(target, instr.propertyIndex);
571 float f = instr.value;
572 void *a[] = { &f, 0, &status, &flags };
573 QMetaObject::metacall(target, QMetaObject::WriteProperty,
574 instr.propertyIndex, a);
575 QML_END_INSTR(StoreFloat)
577 QML_BEGIN_INSTR(StoreDouble)
578 QObject *target = objects.top();
579 CLEAN_PROPERTY(target, instr.propertyIndex);
581 double d = instr.value;
582 void *a[] = { &d, 0, &status, &flags };
583 QMetaObject::metacall(target, QMetaObject::WriteProperty,
584 instr.propertyIndex, a);
585 QML_END_INSTR(StoreDouble)
587 QML_BEGIN_INSTR(StoreBool)
588 QObject *target = objects.top();
589 CLEAN_PROPERTY(target, instr.propertyIndex);
591 void *a[] = { (void *)&instr.value, 0, &status, &flags };
592 QMetaObject::metacall(target, QMetaObject::WriteProperty,
593 instr.propertyIndex, a);
594 QML_END_INSTR(StoreBool)
596 QML_BEGIN_INSTR(StoreInteger)
597 QObject *target = objects.top();
598 CLEAN_PROPERTY(target, instr.propertyIndex);
600 void *a[] = { (void *)&instr.value, 0, &status, &flags };
601 QMetaObject::metacall(target, QMetaObject::WriteProperty,
602 instr.propertyIndex, a);
603 QML_END_INSTR(StoreInteger)
605 QML_BEGIN_INSTR(StoreColor)
606 QObject *target = objects.top();
607 CLEAN_PROPERTY(target, instr.propertyIndex);
609 QColor c = QColor::fromRgba(instr.value);
610 void *a[] = { &c, 0, &status, &flags };
611 QMetaObject::metacall(target, QMetaObject::WriteProperty,
612 instr.propertyIndex, a);
613 QML_END_INSTR(StoreColor)
615 QML_BEGIN_INSTR(StoreDate)
616 QObject *target = objects.top();
617 CLEAN_PROPERTY(target, instr.propertyIndex);
619 QDate d = QDate::fromJulianDay(instr.value);
620 void *a[] = { &d, 0, &status, &flags };
621 QMetaObject::metacall(target, QMetaObject::WriteProperty,
622 instr.propertyIndex, a);
623 QML_END_INSTR(StoreDate)
625 QML_BEGIN_INSTR(StoreTime)
626 QObject *target = objects.top();
627 CLEAN_PROPERTY(target, instr.propertyIndex);
629 QTime *t = (QTime *)&instr.time;
630 void *a[] = { t, 0, &status, &flags };
631 QMetaObject::metacall(target, QMetaObject::WriteProperty,
632 instr.propertyIndex, a);
633 QML_END_INSTR(StoreTime)
635 QML_BEGIN_INSTR(StoreDateTime)
636 QObject *target = objects.top();
637 CLEAN_PROPERTY(target, instr.propertyIndex);
639 QTime *t = (QTime *)&instr.time;
640 QDateTime dt(QDate::fromJulianDay(instr.date), *t);
641 void *a[] = { &dt, 0, &status, &flags };
642 QMetaObject::metacall(target, QMetaObject::WriteProperty,
643 instr.propertyIndex, a);
644 QML_END_INSTR(StoreDateTime)
646 QML_BEGIN_INSTR(StorePoint)
647 QObject *target = objects.top();
648 CLEAN_PROPERTY(target, instr.propertyIndex);
650 QPoint *p = (QPoint *)&instr.point;
651 void *a[] = { p, 0, &status, &flags };
652 QMetaObject::metacall(target, QMetaObject::WriteProperty,
653 instr.propertyIndex, a);
654 QML_END_INSTR(StorePoint)
656 QML_BEGIN_INSTR(StorePointF)
657 QObject *target = objects.top();
658 CLEAN_PROPERTY(target, instr.propertyIndex);
660 QPointF *p = (QPointF *)&instr.point;
661 void *a[] = { p, 0, &status, &flags };
662 QMetaObject::metacall(target, QMetaObject::WriteProperty,
663 instr.propertyIndex, a);
664 QML_END_INSTR(StorePointF)
666 QML_BEGIN_INSTR(StoreSize)
667 QObject *target = objects.top();
668 CLEAN_PROPERTY(target, instr.propertyIndex);
670 QSize *s = (QSize *)&instr.size;
671 void *a[] = { s, 0, &status, &flags };
672 QMetaObject::metacall(target, QMetaObject::WriteProperty,
673 instr.propertyIndex, a);
674 QML_END_INSTR(StoreSize)
676 QML_BEGIN_INSTR(StoreSizeF)
677 QObject *target = objects.top();
678 CLEAN_PROPERTY(target, instr.propertyIndex);
680 QSizeF *s = (QSizeF *)&instr.size;
681 void *a[] = { s, 0, &status, &flags };
682 QMetaObject::metacall(target, QMetaObject::WriteProperty,
683 instr.propertyIndex, a);
684 QML_END_INSTR(StoreSizeF)
686 QML_BEGIN_INSTR(StoreRect)
687 QObject *target = objects.top();
688 CLEAN_PROPERTY(target, instr.propertyIndex);
690 QRect *r = (QRect *)&instr.rect;
691 void *a[] = { r, 0, &status, &flags };
692 QMetaObject::metacall(target, QMetaObject::WriteProperty,
693 instr.propertyIndex, a);
694 QML_END_INSTR(StoreRect)
696 QML_BEGIN_INSTR(StoreRectF)
697 QObject *target = objects.top();
698 CLEAN_PROPERTY(target, instr.propertyIndex);
700 QRectF *r = (QRectF *)&instr.rect;
701 void *a[] = { r, 0, &status, &flags };
702 QMetaObject::metacall(target, QMetaObject::WriteProperty,
703 instr.propertyIndex, a);
704 QML_END_INSTR(StoreRectF)
706 QML_BEGIN_INSTR(StoreVector3D)
707 QObject *target = objects.top();
708 CLEAN_PROPERTY(target, instr.propertyIndex);
710 QVector3D *v = (QVector3D *)&instr.vector;
711 void *a[] = { v, 0, &status, &flags };
712 QMetaObject::metacall(target, QMetaObject::WriteProperty,
713 instr.propertyIndex, a);
714 QML_END_INSTR(StoreVector3D)
716 QML_BEGIN_INSTR(StoreVector4D)
717 QObject *target = objects.top();
718 CLEAN_PROPERTY(target, instr.propertyIndex);
720 QVector4D *v = (QVector4D *)&instr.vector;
721 void *a[] = { v, 0, &status, &flags };
722 QMetaObject::metacall(target, QMetaObject::WriteProperty,
723 instr.propertyIndex, a);
724 QML_END_INSTR(StoreVector4D)
726 QML_BEGIN_INSTR(StoreObject)
727 QObject *assignObj = objects.pop();
728 QObject *target = objects.top();
729 CLEAN_PROPERTY(target, instr.propertyIndex);
731 void *a[] = { (void *)&assignObj, 0, &status, &flags };
732 QMetaObject::metacall(target, QMetaObject::WriteProperty,
733 instr.propertyIndex, a);
734 QML_END_INSTR(StoreObject)
736 QML_BEGIN_INSTR(AssignCustomType)
737 QObject *target = objects.top();
738 CLEAN_PROPERTY(target, instr.propertyIndex);
740 const QString &primitive = PRIMITIVES.at(instr.primitive);
741 int type = instr.type;
742 QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
743 QVariant v = (*converter)(primitive);
746 target->metaObject()->property(instr.propertyIndex);
747 if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
748 VME_EXCEPTION(tr("Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
750 void *a[] = { (void *)v.data(), 0, &status, &flags };
751 QMetaObject::metacall(target, QMetaObject::WriteProperty,
752 instr.propertyIndex, a);
753 QML_END_INSTR(AssignCustomType)
755 QML_BEGIN_INSTR(AssignSignalObject)
758 QObject *assign = objects.pop();
759 QObject *target = objects.top();
760 int sigIdx = instr.signal;
761 const QString &pr = PRIMITIVES.at(sigIdx);
763 QDeclarativeProperty prop(target, pr);
764 if (prop.type() & QDeclarativeProperty::SignalProperty) {
766 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
767 if (method.signature() == 0)
768 VME_EXCEPTION(tr("Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
770 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
771 VME_EXCEPTION(tr("Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.line);
773 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
776 VME_EXCEPTION(tr("Cannot assign an object to signal property %1").arg(pr), instr.line);
780 QML_END_INSTR(AssignSignalObject)
782 QML_BEGIN_INSTR(StoreSignal)
783 QObject *target = objects.top();
784 QObject *context = objects.at(objects.count() - 1 - instr.context);
786 QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
788 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
789 QDeclarativeExpression *expr =
790 new QDeclarativeExpression(CTXT, context, PRIMITIVES.at(instr.value));
791 expr->setSourceLocation(COMP->name, instr.line);
792 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = QString::fromUtf8(DATAS.at(instr.name));
793 bs->setExpression(expr);
794 QML_END_INSTR(StoreSignal)
796 QML_BEGIN_INSTR(StoreImportedScript)
797 CTXT->importedScripts << run(CTXT, SCRIPTS.at(instr.value));
798 QML_END_INSTR(StoreImportedScript)
800 QML_BEGIN_INSTR(StoreScriptString)
801 QObject *target = objects.top();
802 QObject *scope = objects.at(objects.count() - 1 - instr.scope);
803 QDeclarativeScriptString ss;
804 ss.setContext(CTXT->asQDeclarativeContext());
805 ss.setScopeObject(scope);
806 ss.setScript(PRIMITIVES.at(instr.value));
807 ss.d.data()->bindingId = instr.bindingId;
808 ss.d.data()->lineNumber = instr.line;
810 void *a[] = { &ss, 0, &status, &flags };
811 QMetaObject::metacall(target, QMetaObject::WriteProperty,
812 instr.propertyIndex, a);
813 QML_END_INSTR(StoreScriptString)
815 QML_BEGIN_INSTR(BeginObject)
816 QObject *target = objects.top();
817 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
818 parserStatus.push(status);
819 status->d = &parserStatus.top();
821 status->classBegin();
822 QML_END_INSTR(BeginObject)
824 QML_BEGIN_INSTR(InitV8Bindings)
825 CTXT->v8bindings = new QV8Bindings(PRIMITIVES.at(instr.program), instr.programIndex,
826 instr.line, COMP, CTXT);
827 QML_END_INSTR(InitV8Bindings)
829 QML_BEGIN_INSTR(StoreBinding)
831 objects.at(objects.count() - 1 - instr.owner);
833 objects.at(objects.count() - 1 - instr.context);
835 QDeclarativeProperty mp =
836 QDeclarativePropertyPrivate::restore(DATAS.at(instr.property), target, CTXT);
838 int coreIndex = mp.index();
840 if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex))
841 QML_NEXT_INSTR(StoreBinding);
843 QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true,
844 context, CTXT, COMP->name, instr.line);
845 bindValues.push(bind);
846 bind->m_mePtr = &bindValues.top();
849 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
850 QML_END_INSTR(StoreBinding)
852 QML_BEGIN_INSTR(StoreBindingOnAlias)
854 objects.at(objects.count() - 1 - instr.owner);
856 objects.at(objects.count() - 1 - instr.context);
858 QDeclarativeProperty mp =
859 QDeclarativePropertyPrivate::restore(DATAS.at(instr.property), target, CTXT);
861 int coreIndex = mp.index();
863 if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex))
864 QML_NEXT_INSTR(StoreBindingOnAlias);
866 QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true,
867 context, CTXT, COMP->name, instr.line);
868 bindValues.push(bind);
869 bind->m_mePtr = &bindValues.top();
872 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
873 if (old) { old->destroy(); }
874 QML_END_INSTR(StoreBindingOnAlias)
876 QML_BEGIN_INSTR(StoreV4Binding)
878 objects.at(objects.count() - 1 - instr.owner);
880 objects.at(objects.count() - 1 - instr.context);
882 int property = instr.property;
883 if (instr.isRoot && BINDINGSKIPLIST.testBit(property & 0xFFFF))
884 QML_NEXT_INSTR(StoreV4Binding);
886 QDeclarativeAbstractBinding *binding =
887 CTXT->v4bindings->configBinding(instr.value, target, scope, property);
888 bindValues.push(binding);
889 binding->m_mePtr = &bindValues.top();
890 binding->addToObject(target, property);
891 QML_END_INSTR(StoreV4Binding)
893 QML_BEGIN_INSTR(StoreV8Binding)
895 objects.at(objects.count() - 1 - instr.owner);
897 objects.at(objects.count() - 1 - instr.context);
899 QDeclarativeProperty mp =
900 QDeclarativePropertyPrivate::restore(DATAS.at(instr.property), target, CTXT);
902 int coreIndex = mp.index();
904 if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex))
905 QML_NEXT_INSTR(StoreV8Binding);
907 QDeclarativeAbstractBinding *binding =
908 CTXT->v8bindings->configBinding(instr.value, target, scope, mp, instr.line);
909 bindValues.push(binding);
910 binding->m_mePtr = &bindValues.top();
911 binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
912 QML_END_INSTR(StoreV8Binding)
914 QML_BEGIN_INSTR(StoreValueSource)
915 QObject *obj = objects.pop();
916 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
917 QObject *target = objects.at(objects.count() - 1 - instr.owner);
919 QDeclarativeProperty prop =
920 QDeclarativePropertyPrivate::restore(DATAS.at(instr.property), target, CTXT);
921 obj->setParent(target);
923 QML_END_INSTR(StoreValueSource)
925 QML_BEGIN_INSTR(StoreValueInterceptor)
926 QObject *obj = objects.pop();
927 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
928 QObject *target = objects.at(objects.count() - 1 - instr.owner);
929 QDeclarativeProperty prop =
930 QDeclarativePropertyPrivate::restore(DATAS.at(instr.property), target, CTXT);
931 obj->setParent(target);
933 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
934 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
935 QML_END_INSTR(StoreValueInterceptor)
937 QML_BEGIN_INSTR(StoreObjectQList)
938 QObject *assign = objects.pop();
940 const List &list = lists.top();
941 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
942 QML_END_INSTR(StoreObjectQList)
944 QML_BEGIN_INSTR(AssignObjectList)
945 // This is only used for assigning interfaces
946 QObject *assign = objects.pop();
947 const List &list = lists.top();
949 int type = list.type;
953 const char *iid = QDeclarativeMetaType::interfaceIId(type);
955 ptr = assign->qt_metacast(iid);
957 VME_EXCEPTION(tr("Cannot assign object to list"), instr.line);
960 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
961 QML_END_INSTR(AssignObjectList)
963 QML_BEGIN_INSTR(StoreVariantObject)
964 QObject *assign = objects.pop();
965 QObject *target = objects.top();
966 CLEAN_PROPERTY(target, instr.propertyIndex);
968 QVariant v = QVariant::fromValue(assign);
969 void *a[] = { &v, 0, &status, &flags };
970 QMetaObject::metacall(target, QMetaObject::WriteProperty,
971 instr.propertyIndex, a);
972 QML_END_INSTR(StoreVariantObject)
974 QML_BEGIN_INSTR(StoreInterface)
975 QObject *assign = objects.pop();
976 QObject *target = objects.top();
977 CLEAN_PROPERTY(target, instr.propertyIndex);
979 int coreIdx = instr.propertyIndex;
980 QMetaProperty prop = target->metaObject()->property(coreIdx);
981 int t = prop.userType();
982 const char *iid = QDeclarativeMetaType::interfaceIId(t);
985 void *ptr = assign->qt_metacast(iid);
987 void *a[] = { &ptr, 0, &status, &flags };
988 QMetaObject::metacall(target,
989 QMetaObject::WriteProperty,
996 VME_EXCEPTION(tr("Cannot assign object to interface property"), instr.line);
997 QML_END_INSTR(StoreInterface)
999 QML_BEGIN_INSTR(FetchAttached)
1000 QObject *target = objects.top();
1002 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
1005 VME_EXCEPTION(tr("Unable to create attached object"), instr.line);
1007 objects.push(qmlObject);
1008 QML_END_INSTR(FetchAttached)
1010 QML_BEGIN_INSTR(FetchQList)
1011 QObject *target = objects.top();
1013 lists.push(List(instr.type));
1016 a[0] = (void *)&(lists.top().qListProperty);
1017 QMetaObject::metacall(target, QMetaObject::ReadProperty,
1019 QML_END_INSTR(FetchQList)
1021 QML_BEGIN_INSTR(FetchObject)
1022 QObject *target = objects.top();
1025 // NOTE: This assumes a cast to QObject does not alter the
1029 QMetaObject::metacall(target, QMetaObject::ReadProperty,
1033 VME_EXCEPTION(tr("Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line);
1036 QML_END_INSTR(FetchObject)
1038 QML_BEGIN_INSTR(PopQList)
1040 QML_END_INSTR(PopQList)
1042 QML_BEGIN_INSTR(Defer)
1043 if (instr.deferCount) {
1044 QObject *target = objects.top();
1045 QDeclarativeData *data =
1046 QDeclarativeData::get(target, true);
1048 data->deferredComponent = COMP;
1049 data->deferredIdx = INSTRUCTIONSTREAM - COMP->bytecode.constData();
1050 INSTRUCTIONSTREAM += instr.deferCount;
1052 QML_END_INSTR(Defer)
1054 QML_BEGIN_INSTR(PopFetchedObject)
1056 QML_END_INSTR(PopFetchedObject)
1058 QML_BEGIN_INSTR(FetchValueType)
1059 QObject *target = objects.top();
1061 if (instr.bindingSkipList != 0) {
1062 // Possibly need to clear bindings
1063 QDeclarativeData *targetData = QDeclarativeData::get(target);
1065 QDeclarativeAbstractBinding *binding =
1066 QDeclarativePropertyPrivate::binding(target, instr.property, -1);
1068 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
1069 QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
1071 } else if (binding) {
1072 QDeclarativeValueTypeProxyBinding *proxy =
1073 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
1074 proxy->removeBindings(instr.bindingSkipList);
1079 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
1080 valueHandler->read(target, instr.property);
1081 objects.push(valueHandler);
1082 QML_END_INSTR(FetchValueType)
1084 QML_BEGIN_INSTR(PopValueType)
1085 QDeclarativeValueType *valueHandler =
1086 static_cast<QDeclarativeValueType *>(objects.pop());
1087 QObject *target = objects.top();
1088 valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
1089 QML_END_INSTR(PopValueType)
1091 #ifdef QML_THREADED_VME_INTERPRETER
1095 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr->common.instructionType);
1102 if (!objects.isEmpty())
1103 delete objects.at(0); // XXX What about failures in deferred creation?
1105 // XXX does context get leaked in this case?
1107 Q_ASSERT(!errors->isEmpty());
1109 // Remove the QDeclarativeParserStatus and QDeclarativeAbstractBinding back pointers
1110 blank(parserStatus);
1113 objects.deallocate();
1116 bindValues.deallocate();
1117 parserStatus.deallocate();
1118 finalizeCallbacks.clear();
1123 Q_ASSERT(objects.count() == 1);
1125 QObject *rv = objects.top();
1127 objects.deallocate();
1134 // Must be called with a handle scope and context
1135 void QDeclarativeScriptData::initialize(QDeclarativeEngine *engine)
1137 Q_ASSERT(m_program.IsEmpty());
1139 Q_ASSERT(!hasEngine());
1141 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
1142 QV8Engine *v8engine = ep->v8engine();
1144 // XXX Handle errors during the script compile!
1145 v8::Local<v8::Script> program = v8engine->qmlModeCompile(m_programSource, url.toString(), 1);
1146 m_program = qPersistentNew<v8::Script>(program);
1148 addToEngine(engine);
1153 v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1155 if (script->m_loaded)
1156 return qPersistentNew<v8::Object>(script->m_value);
1158 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1159 QV8Engine *v8engine = ep->v8engine();
1161 bool shared = script->pragmas & QDeclarativeScript::Object::ScriptBlock::Shared;
1163 QDeclarativeContextData *effectiveCtxt = parentCtxt;
1167 // Create the script context if required
1168 QDeclarativeContextData *ctxt = new QDeclarativeContextData;
1169 ctxt->isInternal = true;
1170 ctxt->isJSContext = true;
1172 ctxt->isPragmaLibraryContext = true;
1174 ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
1175 ctxt->url = script->url;
1177 // For backward compatibility, if there are no imports, we need to use the
1178 // imports from the parent context. See QTBUG-17518.
1179 if (!script->importCache->isEmpty()) {
1180 ctxt->imports = script->importCache;
1181 } else if (effectiveCtxt) {
1182 ctxt->imports = effectiveCtxt->imports;
1183 ctxt->importedScripts = effectiveCtxt->importedScripts;
1184 for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
1185 ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
1188 if (ctxt->imports) {
1189 ctxt->imports->addref();
1193 ctxt->setParent(effectiveCtxt, true);
1195 for (int ii = 0; ii < script->scripts.count(); ++ii) {
1196 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1199 v8::HandleScope handle_scope;
1200 v8::Context::Scope scope(v8engine->context());
1202 if (!script->isInitialized())
1203 script->initialize(parentCtxt->engine);
1205 v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
1207 v8::TryCatch try_catch;
1208 script->m_program->Run(qmlglobal);
1210 v8::Persistent<v8::Object> rv;
1212 if (try_catch.HasCaught()) {
1213 v8::Local<v8::Message> message = try_catch.Message();
1214 if (!message.IsEmpty()) {
1215 QDeclarativeError error;
1216 QDeclarativeExpressionPrivate::exceptionToError(message, error);
1221 rv = qPersistentNew<v8::Object>(qmlglobal);
1223 script->m_value = qPersistentNew<v8::Object>(qmlglobal);
1224 script->m_loaded = true;
1230 #ifdef QML_THREADED_VME_INTERPRETER
1231 void **QDeclarativeVME::instructionJumpTable()
1233 static void **jumpTable = 0;
1235 QDeclarativeVME dummy;
1236 QDeclarativeVME::Interrupt i;
1237 dummy.run(0, i, &jumpTable);
1243 bool QDeclarativeVME::complete(const Interrupt &interrupt)
1245 ActiveVMERestorer restore(this, QDeclarativeEnginePrivate::get(engine));
1247 while (!bindValues.isEmpty()) {
1248 QDeclarativeAbstractBinding *b = bindValues.pop();
1252 b->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor |
1253 QDeclarativePropertyPrivate::DontRemoveBinding);
1256 if (interrupt.shouldInterrupt())
1259 bindValues.deallocate();
1261 while (!parserStatus.isEmpty()) {
1262 QDeclarativeParserStatus *status = parserStatus.pop();
1264 if (status && status->d) {
1266 status->componentComplete();
1269 if (interrupt.shouldInterrupt())
1272 parserStatus.deallocate();
1274 while (componentAttached) {
1275 QDeclarativeComponentAttached *a = componentAttached;
1277 QDeclarativeData *d = QDeclarativeData::get(a->parent());
1279 Q_ASSERT(d->context);
1280 a->add(&d->context->componentAttached);
1281 emit a->completed();
1283 if (interrupt.shouldInterrupt())
1287 // XXX (what if its deleted?)
1289 rootContext->activeVME = 0;
1291 for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) {
1292 QDeclarativeEnginePrivate::FinalizeCallback callback = finalizeCallbacks.at(ii);
1293 QObject *obj = callback.first;
1295 void *args[] = { 0 };
1296 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
1299 finalizeCallbacks.clear();
1304 void QDeclarativeVME::blank(QFiniteStack<QDeclarativeAbstractBinding *> &bs)
1306 for (int ii = 0; ii < bs.count(); ++ii) {
1307 QDeclarativeAbstractBinding *b = bs.at(ii);
1308 if (b) b->m_mePtr = 0;
1312 void QDeclarativeVME::blank(QFiniteStack<QDeclarativeParserStatus *> &pss)
1314 for (int ii = 0; ii < pss.count(); ++ii) {
1315 QDeclarativeParserStatus *ps = pss.at(ii);