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 "qdeclarativescriptstring.h"
65 #include "qdeclarativescriptstring_p.h"
72 #include <QtCore/qdebug.h>
73 #include <QtCore/qvarlengtharray.h>
74 #include <QtCore/qcoreapplication.h>
75 #include <QtCore/qdatetime.h>
76 #include <QtCore/qvarlengtharray.h>
77 #include <QtDeclarative/qjsvalue.h>
81 // A simple stack wrapper around QVarLengthArray
83 class QDeclarativeVMEStack : private QVarLengthArray<T, 128>
86 typedef QVarLengthArray<T, 128> VLA;
90 inline QDeclarativeVMEStack();
91 inline bool isEmpty() const;
92 inline const T &top() const;
93 inline void push(const T &o);
95 inline int count() const;
96 inline const T &at(int index) const;
99 // We do this so we can forward declare the type in the qdeclarativevme_p.h header
100 class QDeclarativeVMEObjectStack : public QDeclarativeVMEStack<QObject *> {};
102 QDeclarativeVME::QDeclarativeVME()
106 #define VME_EXCEPTION(desc, line) \
108 QDeclarativeError error; \
109 error.setDescription(desc.trimmed()); \
110 error.setLine(line); \
111 error.setUrl(comp->url); \
112 vmeErrors << error; \
124 QDeclarativeListProperty<void> qListProperty;
127 Q_DECLARE_TYPEINFO(ListInstance, Q_PRIMITIVE_TYPE | Q_MOVABLE_TYPE);
129 QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp,
130 int start, const QBitField &bindingSkipList)
132 QDeclarativeVMEObjectStack stack;
134 if (start == -1) start = 0;
136 return run(stack, ctxt, comp, start, bindingSkipList);
139 void QDeclarativeVME::runDeferred(QObject *object)
141 QDeclarativeData *data = QDeclarativeData::get(object);
143 if (!data || !data->context || !data->deferredComponent)
146 QDeclarativeContextData *ctxt = data->context;
147 QDeclarativeCompiledData *comp = data->deferredComponent;
148 int start = data->deferredIdx;
149 QDeclarativeVMEObjectStack stack;
152 run(stack, ctxt, comp, start, QBitField());
155 inline bool fastHasBinding(QObject *o, int index)
157 QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
159 return ddata && (ddata->bindingBitsSize > index) &&
160 (ddata->bindingBits[index / 32] & (1 << (index % 32)));
163 static void removeBindingOnProperty(QObject *o, int index)
165 QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
166 if (binding) binding->destroy();
169 #define QML_BEGIN_INSTR(I) \
170 case QDeclarativeInstruction::I: { \
171 const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(genericInstr); \
172 instructionStream += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \
175 #define QML_END_INSTR(I) } break;
177 #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
179 QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack,
180 QDeclarativeContextData *ctxt,
181 QDeclarativeCompiledData *comp,
182 int start, const QBitField &bindingSkipList)
186 const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types;
187 const QList<QString> &primitives = comp->primitives;
188 const QList<QByteArray> &datas = comp->datas;
189 const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches;
190 const QList<QDeclarativeScriptData *> &scripts = comp->scripts;
191 const QList<QUrl> &urls = comp->urls;
193 QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues;
194 QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus;
196 QDeclarativeVMEStack<ListInstance> qliststack;
199 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
201 int status = -1; //for dbus
202 QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
203 QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
205 const char *instructionStream = comp->bytecode.constData() + start;
208 while (!isError() && !done) {
209 const QDeclarativeInstruction &genericInstr = *((QDeclarativeInstruction *)instructionStream);
211 switch(genericInstr.type()) {
212 QML_BEGIN_INSTR(Init)
213 if (instr.bindingsSize)
214 bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.bindingsSize);
215 if (instr.parserStatusSize)
216 parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.parserStatusSize);
217 if (instr.contextCache != -1)
218 ctxt->setIdPropertyData(comp->contextCaches.at(instr.contextCache));
219 if (instr.compiledBinding != -1) {
220 const char *v4data = datas.at(instr.compiledBinding).constData();
221 ctxt->v4bindings = new QDeclarativeV4Bindings(v4data, ctxt, comp);
225 QML_BEGIN_INSTR(Done)
229 QML_BEGIN_INSTR(CreateObject)
231 if (instr.bindingBits != -1) {
232 const QByteArray &bits = datas.at(instr.bindingBits);
233 bindings = QBitField((const quint32*)bits.constData(),
237 bindings = bindings.united(bindingSkipList);
240 types.at(instr.type).createInstance(ctxt, bindings, &vmeErrors);
243 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(types.at(instr.type).className), instr.line);
246 QDeclarativeData *ddata = QDeclarativeData::get(o);
249 if (stack.isEmpty()) {
250 if (ddata->context) {
251 Q_ASSERT(ddata->context != ctxt);
252 Q_ASSERT(ddata->outerContext);
253 Q_ASSERT(ddata->outerContext != ctxt);
254 QDeclarativeContextData *c = ddata->context;
255 while (c->linkedContext) c = c->linkedContext;
256 c->linkedContext = ctxt;
261 ddata->ownContext = true;
262 } else if (!ddata->context) {
266 ddata->setImplicitDestructible();
267 ddata->outerContext = ctxt;
268 ddata->lineNumber = instr.line;
269 ddata->columnNumber = instr.column;
271 if (instr.data != -1) {
272 QDeclarativeCustomParser *customParser =
273 types.at(instr.type).type->customParser();
274 customParser->setCustomData(o, datas.at(instr.data));
276 if (!stack.isEmpty()) {
277 QObject *parent = stack.top();
278 #if 0 // ### refactor
279 if (o->isWidgetType()) {
280 QWidget *widget = static_cast<QWidget*>(o);
281 if (parent->isWidgetType()) {
282 QWidget *parentWidget = static_cast<QWidget*>(parent);
283 widget->setParent(parentWidget);
285 // TODO: parent might be a layout
290 QDeclarative_setParent_noEvent(o, parent);
294 QML_END_INSTR(CreateObject)
296 QML_BEGIN_INSTR(CreateSimpleObject)
297 QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));
298 ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
301 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
302 const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.type);
303 if (!ddata->propertyCache && ref.typePropertyCache) {
304 ddata->propertyCache = ref.typePropertyCache;
305 ddata->propertyCache->addref();
307 ddata->lineNumber = instr.line;
308 ddata->columnNumber = instr.column;
310 QObjectPrivate::get(o)->declarativeData = ddata;
311 ddata->context = ddata->outerContext = ctxt;
312 ddata->nextContextObject = ctxt->contextObjects;
313 if (ddata->nextContextObject)
314 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
315 ddata->prevContextObject = &ctxt->contextObjects;
316 ctxt->contextObjects = ddata;
318 QObject *parent = stack.top();
319 QDeclarative_setParent_noEvent(o, parent);
322 QML_END_INSTR(CreateSimpleObject)
324 QML_BEGIN_INSTR(SetId)
325 QObject *target = stack.top();
326 ctxt->setIdProperty(instr.index, target);
329 QML_BEGIN_INSTR(SetDefault)
330 ctxt->contextObject = stack.top();
331 QML_END_INSTR(SetDefault)
333 QML_BEGIN_INSTR(CreateComponent)
334 QDeclarativeComponent *qcomp =
335 new QDeclarativeComponent(ctxt->engine, comp, instructionStream - comp->bytecode.constData(),
336 stack.isEmpty() ? 0 : stack.top());
338 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
341 ctxt->addObject(qcomp);
344 ddata->ownContext = true;
346 ddata->setImplicitDestructible();
347 ddata->outerContext = ctxt;
348 ddata->lineNumber = instr.line;
349 ddata->columnNumber = instr.column;
351 QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
354 instructionStream += instr.count;
355 QML_END_INSTR(CreateComponent)
357 QML_BEGIN_INSTR(StoreMetaObject)
358 QObject *target = stack.top();
361 const QByteArray &metadata = datas.at(instr.data);
362 QFastMetaBuilder::fromData(&mo, 0, metadata);
363 // QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
366 const QDeclarativeVMEMetaData *data =
367 (const QDeclarativeVMEMetaData *)datas.at(instr.aliasData).constData();
369 (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
371 if (instr.propertyCache != -1) {
372 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
373 if (ddata->propertyCache) ddata->propertyCache->release();
374 ddata->propertyCache = propertyCaches.at(instr.propertyCache);
375 ddata->propertyCache->addref();
377 QML_END_INSTR(StoreMetaObject)
379 QML_BEGIN_INSTR(StoreVariant)
380 QObject *target = stack.top();
381 CLEAN_PROPERTY(target, instr.propertyIndex);
383 // XXX - can be more efficient
384 QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.value));
385 void *a[] = { &v, 0, &status, &flags };
386 QMetaObject::metacall(target, QMetaObject::WriteProperty,
387 instr.propertyIndex, a);
388 QML_END_INSTR(StoreVariant)
390 QML_BEGIN_INSTR(StoreVariantInteger)
391 QObject *target = stack.top();
392 CLEAN_PROPERTY(target, instr.propertyIndex);
394 QVariant v(instr.value);
395 void *a[] = { &v, 0, &status, &flags };
396 QMetaObject::metacall(target, QMetaObject::WriteProperty,
397 instr.propertyIndex, a);
398 QML_END_INSTR(StoreVariantInteger)
400 QML_BEGIN_INSTR(StoreVariantDouble)
401 QObject *target = stack.top();
402 CLEAN_PROPERTY(target, instr.propertyIndex);
404 QVariant v(instr.value);
405 void *a[] = { &v, 0, &status, &flags };
406 QMetaObject::metacall(target, QMetaObject::WriteProperty,
407 instr.propertyIndex, a);
408 QML_END_INSTR(StoreVariantDouble)
410 QML_BEGIN_INSTR(StoreVariantBool)
411 QObject *target = stack.top();
412 CLEAN_PROPERTY(target, instr.propertyIndex);
414 QVariant v(instr.value);
415 void *a[] = { &v, 0, &status, &flags };
416 QMetaObject::metacall(target, QMetaObject::WriteProperty,
417 instr.propertyIndex, a);
418 QML_END_INSTR(StoreVariantBool)
420 QML_BEGIN_INSTR(StoreString)
421 QObject *target = stack.top();
422 CLEAN_PROPERTY(target, instr.propertyIndex);
424 void *a[] = { (void *)&primitives.at(instr.value), 0, &status, &flags };
425 QMetaObject::metacall(target, QMetaObject::WriteProperty,
426 instr.propertyIndex, a);
427 QML_END_INSTR(StoreString)
429 QML_BEGIN_INSTR(StoreByteArray)
430 QObject *target = stack.top();
431 void *a[] = { (void *)&datas.at(instr.value), 0, &status, &flags };
432 QMetaObject::metacall(target, QMetaObject::WriteProperty,
433 instr.propertyIndex, a);
434 QML_END_INSTR(StoreByteArray)
436 QML_BEGIN_INSTR(StoreUrl)
437 QObject *target = stack.top();
438 CLEAN_PROPERTY(target, instr.propertyIndex);
440 void *a[] = { (void *)&urls.at(instr.value), 0, &status, &flags };
441 QMetaObject::metacall(target, QMetaObject::WriteProperty,
442 instr.propertyIndex, a);
443 QML_END_INSTR(StoreUrl)
445 QML_BEGIN_INSTR(StoreFloat)
446 QObject *target = stack.top();
447 CLEAN_PROPERTY(target, instr.propertyIndex);
449 float f = instr.value;
450 void *a[] = { &f, 0, &status, &flags };
451 QMetaObject::metacall(target, QMetaObject::WriteProperty,
452 instr.propertyIndex, a);
453 QML_END_INSTR(StoreFloat)
455 QML_BEGIN_INSTR(StoreDouble)
456 QObject *target = stack.top();
457 CLEAN_PROPERTY(target, instr.propertyIndex);
459 double d = instr.value;
460 void *a[] = { &d, 0, &status, &flags };
461 QMetaObject::metacall(target, QMetaObject::WriteProperty,
462 instr.propertyIndex, a);
463 QML_END_INSTR(StoreDouble)
465 QML_BEGIN_INSTR(StoreBool)
466 QObject *target = stack.top();
467 CLEAN_PROPERTY(target, instr.propertyIndex);
469 void *a[] = { (void *)&instr.value, 0, &status, &flags };
470 QMetaObject::metacall(target, QMetaObject::WriteProperty,
471 instr.propertyIndex, a);
472 QML_END_INSTR(StoreBool)
474 QML_BEGIN_INSTR(StoreInteger)
475 QObject *target = stack.top();
476 CLEAN_PROPERTY(target, instr.propertyIndex);
478 void *a[] = { (void *)&instr.value, 0, &status, &flags };
479 QMetaObject::metacall(target, QMetaObject::WriteProperty,
480 instr.propertyIndex, a);
481 QML_END_INSTR(StoreInteger)
483 QML_BEGIN_INSTR(StoreColor)
484 QObject *target = stack.top();
485 CLEAN_PROPERTY(target, instr.propertyIndex);
487 QColor c = QColor::fromRgba(instr.value);
488 void *a[] = { &c, 0, &status, &flags };
489 QMetaObject::metacall(target, QMetaObject::WriteProperty,
490 instr.propertyIndex, a);
491 QML_END_INSTR(StoreColor)
493 QML_BEGIN_INSTR(StoreDate)
494 QObject *target = stack.top();
495 CLEAN_PROPERTY(target, instr.propertyIndex);
497 QDate d = QDate::fromJulianDay(instr.value);
498 void *a[] = { &d, 0, &status, &flags };
499 QMetaObject::metacall(target, QMetaObject::WriteProperty,
500 instr.propertyIndex, a);
501 QML_END_INSTR(StoreDate)
503 QML_BEGIN_INSTR(StoreTime)
504 QObject *target = stack.top();
505 CLEAN_PROPERTY(target, instr.propertyIndex);
507 QTime *t = (QTime *)&instr.time;
508 void *a[] = { t, 0, &status, &flags };
509 QMetaObject::metacall(target, QMetaObject::WriteProperty,
510 instr.propertyIndex, a);
511 QML_END_INSTR(StoreTime)
513 QML_BEGIN_INSTR(StoreDateTime)
514 QObject *target = stack.top();
515 CLEAN_PROPERTY(target, instr.propertyIndex);
517 QTime *t = (QTime *)&instr.time;
518 QDateTime dt(QDate::fromJulianDay(instr.date), *t);
519 void *a[] = { &dt, 0, &status, &flags };
520 QMetaObject::metacall(target, QMetaObject::WriteProperty,
521 instr.propertyIndex, a);
522 QML_END_INSTR(StoreDateTime)
524 QML_BEGIN_INSTR(StorePoint)
525 QObject *target = stack.top();
526 CLEAN_PROPERTY(target, instr.propertyIndex);
528 QPoint *p = (QPoint *)&instr.point;
529 void *a[] = { p, 0, &status, &flags };
530 QMetaObject::metacall(target, QMetaObject::WriteProperty,
531 instr.propertyIndex, a);
532 QML_END_INSTR(StorePoint)
534 QML_BEGIN_INSTR(StorePointF)
535 QObject *target = stack.top();
536 CLEAN_PROPERTY(target, instr.propertyIndex);
538 QPointF *p = (QPointF *)&instr.point;
539 void *a[] = { p, 0, &status, &flags };
540 QMetaObject::metacall(target, QMetaObject::WriteProperty,
541 instr.propertyIndex, a);
542 QML_END_INSTR(StorePointF)
544 QML_BEGIN_INSTR(StoreSize)
545 QObject *target = stack.top();
546 CLEAN_PROPERTY(target, instr.propertyIndex);
548 QSize *s = (QSize *)&instr.size;
549 void *a[] = { s, 0, &status, &flags };
550 QMetaObject::metacall(target, QMetaObject::WriteProperty,
551 instr.propertyIndex, a);
552 QML_END_INSTR(StoreSize)
554 QML_BEGIN_INSTR(StoreSizeF)
555 QObject *target = stack.top();
556 CLEAN_PROPERTY(target, instr.propertyIndex);
558 QSizeF *s = (QSizeF *)&instr.size;
559 void *a[] = { s, 0, &status, &flags };
560 QMetaObject::metacall(target, QMetaObject::WriteProperty,
561 instr.propertyIndex, a);
562 QML_END_INSTR(StoreSizeF)
564 QML_BEGIN_INSTR(StoreRect)
565 QObject *target = stack.top();
566 CLEAN_PROPERTY(target, instr.propertyIndex);
568 QRect *r = (QRect *)&instr.rect;
569 void *a[] = { r, 0, &status, &flags };
570 QMetaObject::metacall(target, QMetaObject::WriteProperty,
571 instr.propertyIndex, a);
572 QML_END_INSTR(StoreRect)
574 QML_BEGIN_INSTR(StoreRectF)
575 QObject *target = stack.top();
576 CLEAN_PROPERTY(target, instr.propertyIndex);
578 QRectF *r = (QRectF *)&instr.rect;
579 void *a[] = { r, 0, &status, &flags };
580 QMetaObject::metacall(target, QMetaObject::WriteProperty,
581 instr.propertyIndex, a);
582 QML_END_INSTR(StoreRectF)
584 QML_BEGIN_INSTR(StoreVector3D)
585 QObject *target = stack.top();
586 CLEAN_PROPERTY(target, instr.propertyIndex);
588 QVector3D *v = (QVector3D *)&instr.vector;
589 void *a[] = { v, 0, &status, &flags };
590 QMetaObject::metacall(target, QMetaObject::WriteProperty,
591 instr.propertyIndex, a);
592 QML_END_INSTR(StoreVector3D)
594 QML_BEGIN_INSTR(StoreVector4D)
595 QObject *target = stack.top();
596 CLEAN_PROPERTY(target, instr.propertyIndex);
598 QVector4D *v = (QVector4D *)&instr.vector;
599 void *a[] = { v, 0, &status, &flags };
600 QMetaObject::metacall(target, QMetaObject::WriteProperty,
601 instr.propertyIndex, a);
602 QML_END_INSTR(StoreVector4D)
604 QML_BEGIN_INSTR(StoreObject)
605 QObject *assignObj = stack.pop();
606 QObject *target = stack.top();
607 CLEAN_PROPERTY(target, instr.propertyIndex);
609 void *a[] = { (void *)&assignObj, 0, &status, &flags };
610 QMetaObject::metacall(target, QMetaObject::WriteProperty,
611 instr.propertyIndex, a);
612 QML_END_INSTR(StoreObject)
614 QML_BEGIN_INSTR(AssignCustomType)
615 QObject *target = stack.top();
616 CLEAN_PROPERTY(target, instr.propertyIndex);
618 const QString &primitive = primitives.at(instr.primitive);
619 int type = instr.type;
620 QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
621 QVariant v = (*converter)(primitive);
624 target->metaObject()->property(instr.propertyIndex);
625 if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
626 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
628 void *a[] = { (void *)v.data(), 0, &status, &flags };
629 QMetaObject::metacall(target, QMetaObject::WriteProperty,
630 instr.propertyIndex, a);
631 QML_END_INSTR(AssignCustomType)
633 QML_BEGIN_INSTR(AssignSignalObject)
636 QObject *assign = stack.pop();
637 QObject *target = stack.top();
638 int sigIdx = instr.signal;
639 const QString &pr = primitives.at(sigIdx);
641 QDeclarativeProperty prop(target, pr);
642 if (prop.type() & QDeclarativeProperty::SignalProperty) {
644 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
645 if (method.signature() == 0)
646 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
648 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
649 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.line);
651 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
654 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(pr), instr.line);
658 QML_END_INSTR(AssignSignalObject)
660 QML_BEGIN_INSTR(StoreSignal)
661 QObject *target = stack.top();
662 QObject *context = stack.at(stack.count() - 1 - instr.context);
664 QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
666 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
667 QDeclarativeExpression *expr =
668 new QDeclarativeExpression(ctxt, context, primitives.at(instr.value));
669 expr->setSourceLocation(comp->name, instr.line);
670 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.name);
671 bs->setExpression(expr);
672 QML_END_INSTR(StoreSignal)
674 QML_BEGIN_INSTR(StoreImportedScript)
675 ctxt->importedScripts << run(ctxt, scripts.at(instr.value));
676 QML_END_INSTR(StoreImportedScript)
678 QML_BEGIN_INSTR(StoreScriptString)
679 QObject *target = stack.top();
680 QObject *scope = stack.at(stack.count() - 1 - instr.scope);
681 QDeclarativeScriptString ss;
682 ss.setContext(ctxt->asQDeclarativeContext());
683 ss.setScopeObject(scope);
684 ss.setScript(primitives.at(instr.value));
685 ss.d.data()->bindingId = instr.bindingId;
686 ss.d.data()->lineNumber = instr.line;
688 void *a[] = { &ss, 0, &status, &flags };
689 QMetaObject::metacall(target, QMetaObject::WriteProperty,
690 instr.propertyIndex, a);
691 QML_END_INSTR(StoreScriptString)
693 QML_BEGIN_INSTR(BeginObject)
694 QObject *target = stack.top();
695 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
696 parserStatus.append(status);
697 status->d = &parserStatus.values[parserStatus.count - 1];
699 status->classBegin();
700 QML_END_INSTR(BeginObject)
702 QML_BEGIN_INSTR(InitV8Bindings)
703 ctxt->v8bindings = new QV8Bindings(primitives.at(instr.program), instr.programIndex,
704 instr.line, comp, ctxt);
705 QML_END_INSTR(InitV8Bindings)
707 QML_BEGIN_INSTR(StoreBinding)
709 stack.at(stack.count() - 1 - instr.owner);
711 stack.at(stack.count() - 1 - instr.context);
713 QDeclarativeProperty mp =
714 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
716 int coreIndex = mp.index();
718 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
721 QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
722 context, ctxt, comp->name, instr.line);
723 bindValues.append(bind);
724 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
727 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
728 QML_END_INSTR(StoreBinding)
730 QML_BEGIN_INSTR(StoreBindingOnAlias)
732 stack.at(stack.count() - 1 - instr.owner);
734 stack.at(stack.count() - 1 - instr.context);
736 QDeclarativeProperty mp =
737 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
739 int coreIndex = mp.index();
741 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
744 QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
745 context, ctxt, comp->name, instr.line);
746 bindValues.append(bind);
747 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
750 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
751 if (old) { old->destroy(); }
752 QML_END_INSTR(StoreBindingOnAlias)
754 QML_BEGIN_INSTR(StoreV4Binding)
756 stack.at(stack.count() - 1 - instr.owner);
758 stack.at(stack.count() - 1 - instr.context);
760 int property = instr.property;
761 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
764 QDeclarativeAbstractBinding *binding =
765 ctxt->v4bindings->configBinding(instr.value, target, scope, property);
766 bindValues.append(binding);
767 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
768 binding->addToObject(target, property);
769 QML_END_INSTR(StoreV4Binding)
771 QML_BEGIN_INSTR(StoreV8Binding)
773 stack.at(stack.count() - 1 - instr.owner);
775 stack.at(stack.count() - 1 - instr.context);
777 QDeclarativeProperty mp =
778 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
780 int coreIndex = mp.index();
782 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
785 QDeclarativeAbstractBinding *binding =
786 ctxt->v8bindings->configBinding(instr.value, target, scope, mp, instr.line);
787 bindValues.append(binding);
788 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
789 binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
790 QML_END_INSTR(StoreV8Binding)
792 QML_BEGIN_INSTR(StoreValueSource)
793 QObject *obj = stack.pop();
794 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
795 QObject *target = stack.at(stack.count() - 1 - instr.owner);
797 QDeclarativeProperty prop =
798 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
799 obj->setParent(target);
801 QML_END_INSTR(StoreValueSource)
803 QML_BEGIN_INSTR(StoreValueInterceptor)
804 QObject *obj = stack.pop();
805 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
806 QObject *target = stack.at(stack.count() - 1 - instr.owner);
807 QDeclarativeProperty prop =
808 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
809 obj->setParent(target);
811 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
812 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
813 QML_END_INSTR(StoreValueInterceptor)
815 QML_BEGIN_INSTR(StoreObjectQList)
816 QObject *assign = stack.pop();
818 const ListInstance &list = qliststack.top();
819 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
820 QML_END_INSTR(StoreObjectQList)
822 QML_BEGIN_INSTR(AssignObjectList)
823 // This is only used for assigning interfaces
824 QObject *assign = stack.pop();
825 const ListInstance &list = qliststack.top();
827 int type = list.type;
831 const char *iid = QDeclarativeMetaType::interfaceIId(type);
833 ptr = assign->qt_metacast(iid);
835 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line);
838 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
839 QML_END_INSTR(AssignObjectList)
841 QML_BEGIN_INSTR(StoreVariantObject)
842 QObject *assign = stack.pop();
843 QObject *target = stack.top();
844 CLEAN_PROPERTY(target, instr.propertyIndex);
846 QVariant v = QVariant::fromValue(assign);
847 void *a[] = { &v, 0, &status, &flags };
848 QMetaObject::metacall(target, QMetaObject::WriteProperty,
849 instr.propertyIndex, a);
850 QML_END_INSTR(StoreVariantObject)
852 QML_BEGIN_INSTR(StoreInterface)
853 QObject *assign = stack.pop();
854 QObject *target = stack.top();
855 CLEAN_PROPERTY(target, instr.propertyIndex);
857 int coreIdx = instr.propertyIndex;
858 QMetaProperty prop = target->metaObject()->property(coreIdx);
859 int t = prop.userType();
860 const char *iid = QDeclarativeMetaType::interfaceIId(t);
863 void *ptr = assign->qt_metacast(iid);
865 void *a[] = { &ptr, 0, &status, &flags };
866 QMetaObject::metacall(target,
867 QMetaObject::WriteProperty,
874 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line);
875 QML_END_INSTR(StoreInterface)
877 QML_BEGIN_INSTR(FetchAttached)
878 QObject *target = stack.top();
880 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
883 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line);
885 stack.push(qmlObject);
886 QML_END_INSTR(FetchAttached)
888 QML_BEGIN_INSTR(FetchQList)
889 QObject *target = stack.top();
891 qliststack.push(ListInstance(instr.type));
894 a[0] = (void *)&(qliststack.top().qListProperty);
895 QMetaObject::metacall(target, QMetaObject::ReadProperty,
897 QML_END_INSTR(FetchQList)
899 QML_BEGIN_INSTR(FetchObject)
900 QObject *target = stack.top();
903 // NOTE: This assumes a cast to QObject does not alter the
907 QMetaObject::metacall(target, QMetaObject::ReadProperty,
911 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line);
914 QML_END_INSTR(FetchObject)
916 QML_BEGIN_INSTR(PopQList)
918 QML_END_INSTR(PopQList)
920 QML_BEGIN_INSTR(Defer)
921 if (instr.deferCount) {
922 QObject *target = stack.top();
923 QDeclarativeData *data =
924 QDeclarativeData::get(target, true);
926 data->deferredComponent = comp;
927 data->deferredIdx = instructionStream - comp->bytecode.constData();
928 instructionStream += instr.deferCount;
932 QML_BEGIN_INSTR(PopFetchedObject)
934 QML_END_INSTR(PopFetchedObject)
936 QML_BEGIN_INSTR(FetchValueType)
937 QObject *target = stack.top();
939 if (instr.bindingSkipList != 0) {
940 // Possibly need to clear bindings
941 QDeclarativeData *targetData = QDeclarativeData::get(target);
943 QDeclarativeAbstractBinding *binding =
944 QDeclarativePropertyPrivate::binding(target, instr.property, -1);
946 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
947 QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
949 } else if (binding) {
950 QDeclarativeValueTypeProxyBinding *proxy =
951 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
952 proxy->removeBindings(instr.bindingSkipList);
957 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
958 valueHandler->read(target, instr.property);
959 stack.push(valueHandler);
960 QML_END_INSTR(FetchValueType)
962 QML_BEGIN_INSTR(PopValueType)
963 QDeclarativeValueType *valueHandler =
964 static_cast<QDeclarativeValueType *>(stack.pop());
965 QObject *target = stack.top();
966 valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
967 QML_END_INSTR(PopValueType)
970 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type());
976 if (!stack.isEmpty()) {
977 delete stack.at(0); // ### What about failures in deferred creation?
982 QDeclarativeEnginePrivate::clear(bindValues);
983 QDeclarativeEnginePrivate::clear(parserStatus);
987 if (bindValues.count)
988 ep->bindValues << bindValues;
989 else if (bindValues.values)
992 if (parserStatus.count)
993 ep->parserStatus << parserStatus;
994 else if (parserStatus.values)
995 parserStatus.clear();
997 Q_ASSERT(stack.count() == 1);
1001 bool QDeclarativeVME::isError() const
1003 return !vmeErrors.isEmpty();
1006 QList<QDeclarativeError> QDeclarativeVME::errors() const
1012 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
1013 const QBitField &bindings,
1014 QList<QDeclarativeError> *errors) const
1020 type->create(&rv, &memory, sizeof(QDeclarativeData));
1021 QDeclarativeData *ddata = new (memory) QDeclarativeData;
1022 ddata->ownMemory = false;
1023 QObjectPrivate::get(rv)->declarativeData = ddata;
1025 if (typePropertyCache && !ddata->propertyCache) {
1026 ddata->propertyCache = typePropertyCache;
1027 ddata->propertyCache->addref();
1032 Q_ASSERT(component);
1033 return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings);
1037 v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1039 if (script->m_loaded)
1040 return qPersistentNew<v8::Object>(script->m_value);
1042 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1043 QV8Engine *v8engine = ep->v8engine();
1045 bool shared = script->pragmas & QDeclarativeScript::Object::ScriptBlock::Shared;
1047 QDeclarativeContextData *effectiveCtxt = parentCtxt;
1051 // Create the script context if required
1052 QDeclarativeContextData *ctxt = new QDeclarativeContextData;
1053 ctxt->isInternal = true;
1054 ctxt->isJSContext = true;
1056 ctxt->isPragmaLibraryContext = true;
1058 ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
1059 ctxt->url = script->url;
1061 // For backward compatibility, if there are no imports, we need to use the
1062 // imports from the parent context. See QTBUG-17518.
1063 if (!script->importCache->isEmpty()) {
1064 ctxt->imports = script->importCache;
1065 } else if (effectiveCtxt) {
1066 ctxt->imports = effectiveCtxt->imports;
1067 ctxt->importedScripts = effectiveCtxt->importedScripts;
1068 for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
1069 ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
1072 if (ctxt->imports) {
1073 ctxt->imports->addref();
1077 ctxt->setParent(effectiveCtxt, true);
1079 for (int ii = 0; ii < script->scripts.count(); ++ii) {
1080 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1083 v8::HandleScope handle_scope;
1084 v8::Context::Scope scope(v8engine->context());
1086 v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
1088 v8::TryCatch try_catch;
1089 script->m_program->Run(qmlglobal);
1091 v8::Persistent<v8::Object> rv;
1093 if (try_catch.HasCaught()) {
1094 v8::Local<v8::Message> message = try_catch.Message();
1095 if (!message.IsEmpty()) {
1096 QDeclarativeError error;
1097 QDeclarativeExpressionPrivate::exceptionToError(message, error);
1102 rv = qPersistentNew<v8::Object>(qmlglobal);
1104 script->m_value = qPersistentNew<v8::Object>(qmlglobal);
1105 script->m_loaded = true;
1111 template<typename T>
1112 QDeclarativeVMEStack<T>::QDeclarativeVMEStack()
1117 template<typename T>
1118 bool QDeclarativeVMEStack<T>::isEmpty() const {
1119 return _index == -1;
1122 template<typename T>
1123 const T &QDeclarativeVMEStack<T>::top() const {
1127 template<typename T>
1128 void QDeclarativeVMEStack<T>::push(const T &o) {
1131 Q_ASSERT(_index <= VLA::size());
1132 if (_index == VLA::size())
1135 VLA::data()[_index] = o;
1138 template<typename T>
1139 T QDeclarativeVMEStack<T>::pop() {
1140 Q_ASSERT(_index >= 0);
1142 return VLA::data()[_index + 1];
1145 template<typename T>
1146 int QDeclarativeVMEStack<T>::count() const {
1150 template<typename T>
1151 const T &QDeclarativeVMEStack<T>::at(int index) const {
1152 return VLA::data()[index];