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/qdeclarativedata_p.h"
49 #include "qdeclarative.h"
50 #include "private/qdeclarativecustomparser_p.h"
51 #include "qdeclarativeengine.h"
52 #include "qdeclarativecontext.h"
53 #include "qdeclarativecomponent.h"
54 #include "private/qdeclarativebinding_p.h"
55 #include "private/qdeclarativeengine_p.h"
56 #include "private/qdeclarativecomponent_p.h"
57 #include "private/qdeclarativevmemetaobject_p.h"
58 #include "private/qdeclarativebinding_p_p.h"
59 #include "private/qdeclarativecontext_p.h"
60 #include "private/qdeclarativev4bindings_p.h"
61 #include "private/qv8bindings_p.h"
62 #include "private/qdeclarativeglobal_p.h"
63 #include "qdeclarativescriptstring.h"
64 #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);
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 (o->isWidgetType()) {
279 QWidget *widget = static_cast<QWidget*>(o);
280 if (parent->isWidgetType()) {
281 QWidget *parentWidget = static_cast<QWidget*>(parent);
282 widget->setParent(parentWidget);
284 // TODO: parent might be a layout
287 QDeclarative_setParent_noEvent(o, parent);
291 QML_END_INSTR(CreateObject)
293 QML_BEGIN_INSTR(CreateSimpleObject)
294 QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));
295 ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
298 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
299 const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.type);
300 if (!ddata->propertyCache && ref.typePropertyCache) {
301 ddata->propertyCache = ref.typePropertyCache;
302 ddata->propertyCache->addref();
304 ddata->lineNumber = instr.line;
305 ddata->columnNumber = instr.column;
307 QObjectPrivate::get(o)->declarativeData = ddata;
308 ddata->context = ddata->outerContext = ctxt;
309 ddata->nextContextObject = ctxt->contextObjects;
310 if (ddata->nextContextObject)
311 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
312 ddata->prevContextObject = &ctxt->contextObjects;
313 ctxt->contextObjects = ddata;
315 QObject *parent = stack.top();
316 QDeclarative_setParent_noEvent(o, parent);
319 QML_END_INSTR(CreateSimpleObject)
321 QML_BEGIN_INSTR(SetId)
322 QObject *target = stack.top();
323 ctxt->setIdProperty(instr.index, target);
326 QML_BEGIN_INSTR(SetDefault)
327 ctxt->contextObject = stack.top();
328 QML_END_INSTR(SetDefault)
330 QML_BEGIN_INSTR(CreateComponent)
331 QDeclarativeComponent *qcomp =
332 new QDeclarativeComponent(ctxt->engine, comp, instructionStream - comp->bytecode.constData(),
333 stack.isEmpty() ? 0 : stack.top());
335 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
338 ctxt->addObject(qcomp);
341 ddata->ownContext = true;
343 ddata->setImplicitDestructible();
344 ddata->outerContext = ctxt;
345 ddata->lineNumber = instr.line;
346 ddata->columnNumber = instr.column;
348 QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
351 instructionStream += instr.count;
352 QML_END_INSTR(CreateComponent)
354 QML_BEGIN_INSTR(StoreMetaObject)
355 QObject *target = stack.top();
358 const QByteArray &metadata = datas.at(instr.data);
359 QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
361 const QDeclarativeVMEMetaData *data =
362 (const QDeclarativeVMEMetaData *)datas.at(instr.aliasData).constData();
364 (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
366 if (instr.propertyCache != -1) {
367 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
368 if (ddata->propertyCache) ddata->propertyCache->release();
369 ddata->propertyCache = propertyCaches.at(instr.propertyCache);
370 ddata->propertyCache->addref();
372 QML_END_INSTR(StoreMetaObject)
374 QML_BEGIN_INSTR(StoreVariant)
375 QObject *target = stack.top();
376 CLEAN_PROPERTY(target, instr.propertyIndex);
378 // XXX - can be more efficient
379 QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.value));
380 void *a[] = { &v, 0, &status, &flags };
381 QMetaObject::metacall(target, QMetaObject::WriteProperty,
382 instr.propertyIndex, a);
383 QML_END_INSTR(StoreVariant)
385 QML_BEGIN_INSTR(StoreVariantInteger)
386 QObject *target = stack.top();
387 CLEAN_PROPERTY(target, instr.propertyIndex);
389 QVariant v(instr.value);
390 void *a[] = { &v, 0, &status, &flags };
391 QMetaObject::metacall(target, QMetaObject::WriteProperty,
392 instr.propertyIndex, a);
393 QML_END_INSTR(StoreVariantInteger)
395 QML_BEGIN_INSTR(StoreVariantDouble)
396 QObject *target = stack.top();
397 CLEAN_PROPERTY(target, instr.propertyIndex);
399 QVariant v(instr.value);
400 void *a[] = { &v, 0, &status, &flags };
401 QMetaObject::metacall(target, QMetaObject::WriteProperty,
402 instr.propertyIndex, a);
403 QML_END_INSTR(StoreVariantDouble)
405 QML_BEGIN_INSTR(StoreVariantBool)
406 QObject *target = stack.top();
407 CLEAN_PROPERTY(target, instr.propertyIndex);
409 QVariant v(instr.value);
410 void *a[] = { &v, 0, &status, &flags };
411 QMetaObject::metacall(target, QMetaObject::WriteProperty,
412 instr.propertyIndex, a);
413 QML_END_INSTR(StoreVariantBool)
415 QML_BEGIN_INSTR(StoreString)
416 QObject *target = stack.top();
417 CLEAN_PROPERTY(target, instr.propertyIndex);
419 void *a[] = { (void *)&primitives.at(instr.value), 0, &status, &flags };
420 QMetaObject::metacall(target, QMetaObject::WriteProperty,
421 instr.propertyIndex, a);
422 QML_END_INSTR(StoreString)
424 QML_BEGIN_INSTR(StoreByteArray)
425 QObject *target = stack.top();
426 void *a[] = { (void *)&datas.at(instr.value), 0, &status, &flags };
427 QMetaObject::metacall(target, QMetaObject::WriteProperty,
428 instr.propertyIndex, a);
429 QML_END_INSTR(StoreByteArray)
431 QML_BEGIN_INSTR(StoreUrl)
432 QObject *target = stack.top();
433 CLEAN_PROPERTY(target, instr.propertyIndex);
435 void *a[] = { (void *)&urls.at(instr.value), 0, &status, &flags };
436 QMetaObject::metacall(target, QMetaObject::WriteProperty,
437 instr.propertyIndex, a);
438 QML_END_INSTR(StoreUrl)
440 QML_BEGIN_INSTR(StoreFloat)
441 QObject *target = stack.top();
442 CLEAN_PROPERTY(target, instr.propertyIndex);
444 float f = instr.value;
445 void *a[] = { &f, 0, &status, &flags };
446 QMetaObject::metacall(target, QMetaObject::WriteProperty,
447 instr.propertyIndex, a);
448 QML_END_INSTR(StoreFloat)
450 QML_BEGIN_INSTR(StoreDouble)
451 QObject *target = stack.top();
452 CLEAN_PROPERTY(target, instr.propertyIndex);
454 double d = instr.value;
455 void *a[] = { &d, 0, &status, &flags };
456 QMetaObject::metacall(target, QMetaObject::WriteProperty,
457 instr.propertyIndex, a);
458 QML_END_INSTR(StoreDouble)
460 QML_BEGIN_INSTR(StoreBool)
461 QObject *target = stack.top();
462 CLEAN_PROPERTY(target, instr.propertyIndex);
464 void *a[] = { (void *)&instr.value, 0, &status, &flags };
465 QMetaObject::metacall(target, QMetaObject::WriteProperty,
466 instr.propertyIndex, a);
467 QML_END_INSTR(StoreBool)
469 QML_BEGIN_INSTR(StoreInteger)
470 QObject *target = stack.top();
471 CLEAN_PROPERTY(target, instr.propertyIndex);
473 void *a[] = { (void *)&instr.value, 0, &status, &flags };
474 QMetaObject::metacall(target, QMetaObject::WriteProperty,
475 instr.propertyIndex, a);
476 QML_END_INSTR(StoreInteger)
478 QML_BEGIN_INSTR(StoreColor)
479 QObject *target = stack.top();
480 CLEAN_PROPERTY(target, instr.propertyIndex);
482 QColor c = QColor::fromRgba(instr.value);
483 void *a[] = { &c, 0, &status, &flags };
484 QMetaObject::metacall(target, QMetaObject::WriteProperty,
485 instr.propertyIndex, a);
486 QML_END_INSTR(StoreColor)
488 QML_BEGIN_INSTR(StoreDate)
489 QObject *target = stack.top();
490 CLEAN_PROPERTY(target, instr.propertyIndex);
492 QDate d = QDate::fromJulianDay(instr.value);
493 void *a[] = { &d, 0, &status, &flags };
494 QMetaObject::metacall(target, QMetaObject::WriteProperty,
495 instr.propertyIndex, a);
496 QML_END_INSTR(StoreDate)
498 QML_BEGIN_INSTR(StoreTime)
499 QObject *target = stack.top();
500 CLEAN_PROPERTY(target, instr.propertyIndex);
502 QTime *t = (QTime *)&instr.time;
503 void *a[] = { t, 0, &status, &flags };
504 QMetaObject::metacall(target, QMetaObject::WriteProperty,
505 instr.propertyIndex, a);
506 QML_END_INSTR(StoreTime)
508 QML_BEGIN_INSTR(StoreDateTime)
509 QObject *target = stack.top();
510 CLEAN_PROPERTY(target, instr.propertyIndex);
512 QTime *t = (QTime *)&instr.time;
513 QDateTime dt(QDate::fromJulianDay(instr.date), *t);
514 void *a[] = { &dt, 0, &status, &flags };
515 QMetaObject::metacall(target, QMetaObject::WriteProperty,
516 instr.propertyIndex, a);
517 QML_END_INSTR(StoreDateTime)
519 QML_BEGIN_INSTR(StorePoint)
520 QObject *target = stack.top();
521 CLEAN_PROPERTY(target, instr.propertyIndex);
523 QPoint *p = (QPoint *)&instr.point;
524 void *a[] = { p, 0, &status, &flags };
525 QMetaObject::metacall(target, QMetaObject::WriteProperty,
526 instr.propertyIndex, a);
527 QML_END_INSTR(StorePoint)
529 QML_BEGIN_INSTR(StorePointF)
530 QObject *target = stack.top();
531 CLEAN_PROPERTY(target, instr.propertyIndex);
533 QPointF *p = (QPointF *)&instr.point;
534 void *a[] = { p, 0, &status, &flags };
535 QMetaObject::metacall(target, QMetaObject::WriteProperty,
536 instr.propertyIndex, a);
537 QML_END_INSTR(StorePointF)
539 QML_BEGIN_INSTR(StoreSize)
540 QObject *target = stack.top();
541 CLEAN_PROPERTY(target, instr.propertyIndex);
543 QSize *s = (QSize *)&instr.size;
544 void *a[] = { s, 0, &status, &flags };
545 QMetaObject::metacall(target, QMetaObject::WriteProperty,
546 instr.propertyIndex, a);
547 QML_END_INSTR(StoreSize)
549 QML_BEGIN_INSTR(StoreSizeF)
550 QObject *target = stack.top();
551 CLEAN_PROPERTY(target, instr.propertyIndex);
553 QSizeF *s = (QSizeF *)&instr.size;
554 void *a[] = { s, 0, &status, &flags };
555 QMetaObject::metacall(target, QMetaObject::WriteProperty,
556 instr.propertyIndex, a);
557 QML_END_INSTR(StoreSizeF)
559 QML_BEGIN_INSTR(StoreRect)
560 QObject *target = stack.top();
561 CLEAN_PROPERTY(target, instr.propertyIndex);
563 QRect *r = (QRect *)&instr.rect;
564 void *a[] = { r, 0, &status, &flags };
565 QMetaObject::metacall(target, QMetaObject::WriteProperty,
566 instr.propertyIndex, a);
567 QML_END_INSTR(StoreRect)
569 QML_BEGIN_INSTR(StoreRectF)
570 QObject *target = stack.top();
571 CLEAN_PROPERTY(target, instr.propertyIndex);
573 QRectF *r = (QRectF *)&instr.rect;
574 void *a[] = { r, 0, &status, &flags };
575 QMetaObject::metacall(target, QMetaObject::WriteProperty,
576 instr.propertyIndex, a);
577 QML_END_INSTR(StoreRectF)
579 QML_BEGIN_INSTR(StoreVector3D)
580 QObject *target = stack.top();
581 CLEAN_PROPERTY(target, instr.propertyIndex);
583 QVector3D *v = (QVector3D *)&instr.vector;
584 void *a[] = { v, 0, &status, &flags };
585 QMetaObject::metacall(target, QMetaObject::WriteProperty,
586 instr.propertyIndex, a);
587 QML_END_INSTR(StoreVector3D)
589 QML_BEGIN_INSTR(StoreVector4D)
590 QObject *target = stack.top();
591 CLEAN_PROPERTY(target, instr.propertyIndex);
593 QVector4D *v = (QVector4D *)&instr.vector;
594 void *a[] = { v, 0, &status, &flags };
595 QMetaObject::metacall(target, QMetaObject::WriteProperty,
596 instr.propertyIndex, a);
597 QML_END_INSTR(StoreVector4D)
599 QML_BEGIN_INSTR(StoreObject)
600 QObject *assignObj = stack.pop();
601 QObject *target = stack.top();
602 CLEAN_PROPERTY(target, instr.propertyIndex);
604 void *a[] = { (void *)&assignObj, 0, &status, &flags };
605 QMetaObject::metacall(target, QMetaObject::WriteProperty,
606 instr.propertyIndex, a);
607 QML_END_INSTR(StoreObject)
609 QML_BEGIN_INSTR(AssignCustomType)
610 QObject *target = stack.top();
611 CLEAN_PROPERTY(target, instr.propertyIndex);
613 const QString &primitive = primitives.at(instr.primitive);
614 int type = instr.type;
615 QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
616 QVariant v = (*converter)(primitive);
619 target->metaObject()->property(instr.propertyIndex);
620 if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
621 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
623 void *a[] = { (void *)v.data(), 0, &status, &flags };
624 QMetaObject::metacall(target, QMetaObject::WriteProperty,
625 instr.propertyIndex, a);
626 QML_END_INSTR(AssignCustomType)
628 QML_BEGIN_INSTR(AssignSignalObject)
631 QObject *assign = stack.pop();
632 QObject *target = stack.top();
633 int sigIdx = instr.signal;
634 const QString &pr = primitives.at(sigIdx);
636 QDeclarativeProperty prop(target, pr);
637 if (prop.type() & QDeclarativeProperty::SignalProperty) {
639 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
640 if (method.signature() == 0)
641 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
643 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
644 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);
646 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
649 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(pr), instr.line);
653 QML_END_INSTR(AssignSignalObject)
655 QML_BEGIN_INSTR(StoreSignal)
656 QObject *target = stack.top();
657 QObject *context = stack.at(stack.count() - 1 - instr.context);
659 QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
661 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
662 QDeclarativeExpression *expr =
663 new QDeclarativeExpression(ctxt, context, primitives.at(instr.value));
664 expr->setSourceLocation(comp->name, instr.line);
665 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.name);
666 bs->setExpression(expr);
667 QML_END_INSTR(StoreSignal)
669 QML_BEGIN_INSTR(StoreImportedScript)
670 ctxt->importedScripts << run(ctxt, scripts.at(instr.value));
671 QML_END_INSTR(StoreImportedScript)
673 QML_BEGIN_INSTR(StoreScriptString)
674 QObject *target = stack.top();
675 QObject *scope = stack.at(stack.count() - 1 - instr.scope);
676 QDeclarativeScriptString ss;
677 ss.setContext(ctxt->asQDeclarativeContext());
678 ss.setScopeObject(scope);
679 ss.setScript(primitives.at(instr.value));
680 ss.d.data()->bindingId = instr.bindingId;
681 ss.d.data()->lineNumber = instr.line;
683 void *a[] = { &ss, 0, &status, &flags };
684 QMetaObject::metacall(target, QMetaObject::WriteProperty,
685 instr.propertyIndex, a);
686 QML_END_INSTR(StoreScriptString)
688 QML_BEGIN_INSTR(BeginObject)
689 QObject *target = stack.top();
690 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
691 parserStatus.append(status);
692 status->d = &parserStatus.values[parserStatus.count - 1];
694 status->classBegin();
695 QML_END_INSTR(BeginObject)
697 QML_BEGIN_INSTR(InitV8Bindings)
698 ctxt->v8bindings = new QV8Bindings(primitives.at(instr.program), instr.programIndex,
699 instr.line, comp, ctxt);
700 QML_END_INSTR(InitV8Bindings)
702 QML_BEGIN_INSTR(StoreBinding)
704 stack.at(stack.count() - 1 - instr.owner);
706 stack.at(stack.count() - 1 - instr.context);
708 QDeclarativeProperty mp =
709 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
711 int coreIndex = mp.index();
713 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
716 QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
717 context, ctxt, comp->name, instr.line);
718 bindValues.append(bind);
719 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
722 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
723 QML_END_INSTR(StoreBinding)
725 QML_BEGIN_INSTR(StoreBindingOnAlias)
727 stack.at(stack.count() - 1 - instr.owner);
729 stack.at(stack.count() - 1 - instr.context);
731 QDeclarativeProperty mp =
732 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
734 int coreIndex = mp.index();
736 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
739 QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
740 context, ctxt, comp->name, instr.line);
741 bindValues.append(bind);
742 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
745 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
746 if (old) { old->destroy(); }
747 QML_END_INSTR(StoreBindingOnAlias)
749 QML_BEGIN_INSTR(StoreV4Binding)
751 stack.at(stack.count() - 1 - instr.owner);
753 stack.at(stack.count() - 1 - instr.context);
755 int property = instr.property;
756 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
759 QDeclarativeAbstractBinding *binding =
760 ctxt->v4bindings->configBinding(instr.value, target, scope, property);
761 bindValues.append(binding);
762 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
763 binding->addToObject(target, property);
764 QML_END_INSTR(StoreV4Binding)
766 QML_BEGIN_INSTR(StoreV8Binding)
768 stack.at(stack.count() - 1 - instr.owner);
770 stack.at(stack.count() - 1 - instr.context);
772 QDeclarativeProperty mp =
773 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
775 int coreIndex = mp.index();
777 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
780 QDeclarativeAbstractBinding *binding =
781 ctxt->v8bindings->configBinding(instr.value, target, scope, mp, instr.line);
782 bindValues.append(binding);
783 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
784 binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
785 QML_END_INSTR(StoreV8Binding)
787 QML_BEGIN_INSTR(StoreValueSource)
788 QObject *obj = stack.pop();
789 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
790 QObject *target = stack.at(stack.count() - 1 - instr.owner);
792 QDeclarativeProperty prop =
793 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
794 obj->setParent(target);
796 QML_END_INSTR(StoreValueSource)
798 QML_BEGIN_INSTR(StoreValueInterceptor)
799 QObject *obj = stack.pop();
800 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
801 QObject *target = stack.at(stack.count() - 1 - instr.owner);
802 QDeclarativeProperty prop =
803 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
804 obj->setParent(target);
806 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
807 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
808 QML_END_INSTR(StoreValueInterceptor)
810 QML_BEGIN_INSTR(StoreObjectQList)
811 QObject *assign = stack.pop();
813 const ListInstance &list = qliststack.top();
814 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
815 QML_END_INSTR(StoreObjectQList)
817 QML_BEGIN_INSTR(AssignObjectList)
818 // This is only used for assigning interfaces
819 QObject *assign = stack.pop();
820 const ListInstance &list = qliststack.top();
822 int type = list.type;
826 const char *iid = QDeclarativeMetaType::interfaceIId(type);
828 ptr = assign->qt_metacast(iid);
830 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line);
833 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
834 QML_END_INSTR(AssignObjectList)
836 QML_BEGIN_INSTR(StoreVariantObject)
837 QObject *assign = stack.pop();
838 QObject *target = stack.top();
839 CLEAN_PROPERTY(target, instr.propertyIndex);
841 QVariant v = QVariant::fromValue(assign);
842 void *a[] = { &v, 0, &status, &flags };
843 QMetaObject::metacall(target, QMetaObject::WriteProperty,
844 instr.propertyIndex, a);
845 QML_END_INSTR(StoreVariantObject)
847 QML_BEGIN_INSTR(StoreInterface)
848 QObject *assign = stack.pop();
849 QObject *target = stack.top();
850 CLEAN_PROPERTY(target, instr.propertyIndex);
852 int coreIdx = instr.propertyIndex;
853 QMetaProperty prop = target->metaObject()->property(coreIdx);
854 int t = prop.userType();
855 const char *iid = QDeclarativeMetaType::interfaceIId(t);
858 void *ptr = assign->qt_metacast(iid);
860 void *a[] = { &ptr, 0, &status, &flags };
861 QMetaObject::metacall(target,
862 QMetaObject::WriteProperty,
869 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line);
870 QML_END_INSTR(StoreInterface)
872 QML_BEGIN_INSTR(FetchAttached)
873 QObject *target = stack.top();
875 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
878 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line);
880 stack.push(qmlObject);
881 QML_END_INSTR(FetchAttached)
883 QML_BEGIN_INSTR(FetchQList)
884 QObject *target = stack.top();
886 qliststack.push(ListInstance(instr.type));
889 a[0] = (void *)&(qliststack.top().qListProperty);
890 QMetaObject::metacall(target, QMetaObject::ReadProperty,
892 QML_END_INSTR(FetchQList)
894 QML_BEGIN_INSTR(FetchObject)
895 QObject *target = stack.top();
898 // NOTE: This assumes a cast to QObject does not alter the
902 QMetaObject::metacall(target, QMetaObject::ReadProperty,
906 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);
909 QML_END_INSTR(FetchObject)
911 QML_BEGIN_INSTR(PopQList)
913 QML_END_INSTR(PopQList)
915 QML_BEGIN_INSTR(Defer)
916 if (instr.deferCount) {
917 QObject *target = stack.top();
918 QDeclarativeData *data =
919 QDeclarativeData::get(target, true);
921 data->deferredComponent = comp;
922 data->deferredIdx = instructionStream - comp->bytecode.constData();
923 instructionStream += instr.deferCount;
927 QML_BEGIN_INSTR(PopFetchedObject)
929 QML_END_INSTR(PopFetchedObject)
931 QML_BEGIN_INSTR(FetchValueType)
932 QObject *target = stack.top();
934 if (instr.bindingSkipList != 0) {
935 // Possibly need to clear bindings
936 QDeclarativeData *targetData = QDeclarativeData::get(target);
938 QDeclarativeAbstractBinding *binding =
939 QDeclarativePropertyPrivate::binding(target, instr.property, -1);
941 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
942 QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
944 } else if (binding) {
945 QDeclarativeValueTypeProxyBinding *proxy =
946 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
947 proxy->removeBindings(instr.bindingSkipList);
952 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
953 valueHandler->read(target, instr.property);
954 stack.push(valueHandler);
955 QML_END_INSTR(FetchValueType)
957 QML_BEGIN_INSTR(PopValueType)
958 QDeclarativeValueType *valueHandler =
959 static_cast<QDeclarativeValueType *>(stack.pop());
960 QObject *target = stack.top();
961 valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
962 QML_END_INSTR(PopValueType)
965 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type());
971 if (!stack.isEmpty()) {
972 delete stack.at(0); // ### What about failures in deferred creation?
977 QDeclarativeEnginePrivate::clear(bindValues);
978 QDeclarativeEnginePrivate::clear(parserStatus);
982 if (bindValues.count)
983 ep->bindValues << bindValues;
984 else if (bindValues.values)
987 if (parserStatus.count)
988 ep->parserStatus << parserStatus;
989 else if (parserStatus.values)
990 parserStatus.clear();
992 Q_ASSERT(stack.count() == 1);
996 bool QDeclarativeVME::isError() const
998 return !vmeErrors.isEmpty();
1001 QList<QDeclarativeError> QDeclarativeVME::errors() const
1007 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
1008 const QBitField &bindings,
1009 QList<QDeclarativeError> *errors) const
1015 type->create(&rv, &memory, sizeof(QDeclarativeData));
1016 QDeclarativeData *ddata = new (memory) QDeclarativeData;
1017 ddata->ownMemory = false;
1018 QObjectPrivate::get(rv)->declarativeData = ddata;
1020 if (typePropertyCache && !ddata->propertyCache) {
1021 ddata->propertyCache = typePropertyCache;
1022 ddata->propertyCache->addref();
1027 Q_ASSERT(component);
1028 return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings);
1032 v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1034 if (script->m_loaded)
1035 return qPersistentNew<v8::Object>(script->m_value);
1037 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1038 QV8Engine *v8engine = ep->v8engine();
1040 bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
1042 QDeclarativeContextData *effectiveCtxt = parentCtxt;
1046 // Create the script context if required
1047 QDeclarativeContextData *ctxt = new QDeclarativeContextData;
1048 ctxt->isInternal = true;
1049 ctxt->isJSContext = true;
1051 ctxt->isPragmaLibraryContext = true;
1053 ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
1054 ctxt->url = script->url;
1056 // For backward compatibility, if there are no imports, we need to use the
1057 // imports from the parent context. See QTBUG-17518.
1058 if (!script->importCache->isEmpty()) {
1059 ctxt->imports = script->importCache;
1060 } else if (effectiveCtxt) {
1061 ctxt->imports = effectiveCtxt->imports;
1062 ctxt->importedScripts = effectiveCtxt->importedScripts;
1063 for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
1064 ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
1067 if (ctxt->imports) {
1068 ctxt->imports->addref();
1072 ctxt->setParent(effectiveCtxt, true);
1074 for (int ii = 0; ii < script->scripts.count(); ++ii) {
1075 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1078 v8::HandleScope handle_scope;
1079 v8::Context::Scope scope(v8engine->context());
1081 v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
1083 v8::TryCatch try_catch;
1084 script->m_program->Run(qmlglobal);
1086 v8::Persistent<v8::Object> rv;
1088 if (try_catch.HasCaught()) {
1089 v8::Local<v8::Message> message = try_catch.Message();
1090 if (!message.IsEmpty()) {
1091 QDeclarativeError error;
1092 QDeclarativeExpressionPrivate::exceptionToError(message, error);
1097 rv = qPersistentNew<v8::Object>(qmlglobal);
1099 script->m_value = qPersistentNew<v8::Object>(qmlglobal);
1100 script->m_loaded = true;
1106 template<typename T>
1107 QDeclarativeVMEStack<T>::QDeclarativeVMEStack()
1112 template<typename T>
1113 bool QDeclarativeVMEStack<T>::isEmpty() const {
1114 return _index == -1;
1117 template<typename T>
1118 const T &QDeclarativeVMEStack<T>::top() const {
1122 template<typename T>
1123 void QDeclarativeVMEStack<T>::push(const T &o) {
1126 Q_ASSERT(_index <= VLA::size());
1127 if (_index == VLA::size())
1130 VLA::data()[_index] = o;
1133 template<typename T>
1134 T QDeclarativeVMEStack<T>::pop() {
1135 Q_ASSERT(_index >= 0);
1137 return VLA::data()[_index + 1];
1140 template<typename T>
1141 int QDeclarativeVMEStack<T>::count() const {
1145 template<typename T>
1146 const T &QDeclarativeVMEStack<T>::at(int index) const {
1147 return VLA::data()[index];