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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
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/qdeclarativeglobal_p.h"
62 #include "private/qdeclarativeglobalscriptclass_p.h"
63 #include "qdeclarativescriptstring.h"
71 #include <QtCore/qdebug.h>
72 #include <QtCore/qvarlengtharray.h>
73 #include <QtCore/qcoreapplication.h>
74 #include <QtCore/qdatetime.h>
75 #include <QtScript/qscriptvalue.h>
79 QDeclarativeVME::QDeclarativeVME()
83 #define VME_EXCEPTION(desc) \
85 QDeclarativeError error; \
86 error.setDescription(desc.trimmed()); \
87 error.setLine(instr.line); \
88 error.setUrl(comp->url); \
101 QDeclarativeListProperty<void> qListProperty;
104 QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp,
105 int start, int count, const QBitField &bindingSkipList)
107 QDeclarativeVMEStack<QObject *> stack;
109 if (start == -1) start = 0;
110 if (count == -1) count = comp->bytecode.count();
112 return run(stack, ctxt, comp, start, count, bindingSkipList);
115 void QDeclarativeVME::runDeferred(QObject *object)
117 QDeclarativeData *data = QDeclarativeData::get(object);
119 if (!data || !data->context || !data->deferredComponent)
122 QDeclarativeContextData *ctxt = data->context;
123 QDeclarativeCompiledData *comp = data->deferredComponent;
124 int start = data->deferredIdx + 1;
125 int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount;
126 QDeclarativeVMEStack<QObject *> stack;
129 run(stack, ctxt, comp, start, count, QBitField());
132 inline bool fastHasBinding(QObject *o, int index)
134 QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
136 return ddata && (ddata->bindingBitsSize > index) &&
137 (ddata->bindingBits[index / 32] & (1 << (index % 32)));
140 static void removeBindingOnProperty(QObject *o, int index)
142 QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
143 if (binding) binding->destroy();
146 #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
148 QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
149 QDeclarativeContextData *ctxt,
150 QDeclarativeCompiledData *comp,
151 int start, int count,
152 const QBitField &bindingSkipList)
156 const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types;
157 const QList<QString> &primitives = comp->primitives;
158 const QList<QByteArray> &datas = comp->datas;
159 const QList<QDeclarativeCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
160 const QList<int> &intData = comp->intData;
161 const QList<float> &floatData = comp->floatData;
162 const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches;
163 const QList<QDeclarativeScriptData *> &scripts = comp->scripts;
164 const QList<QUrl> &urls = comp->urls;
166 QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues;
167 QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus;
169 QDeclarativeVMEStack<ListInstance> qliststack;
172 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
174 int status = -1; //for dbus
175 QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
176 QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
178 for (int ii = start; !isError() && ii < (start + count); ++ii) {
179 const QDeclarativeInstruction &instr = comp->bytecode.at(ii);
182 case QDeclarativeInstruction::Init:
184 if (instr.init.bindingsSize)
185 bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.init.bindingsSize);
186 if (instr.init.parserStatusSize)
187 parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.init.parserStatusSize);
188 if (instr.init.contextCache != -1)
189 ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
190 if (instr.init.compiledBinding != -1)
191 ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.init.compiledBinding).constData(), ctxt);
195 case QDeclarativeInstruction::CreateObject:
198 if (instr.create.bindingBits != -1) {
199 const QByteArray &bits = datas.at(instr.create.bindingBits);
200 bindings = QBitField((const quint32*)bits.constData(),
204 bindings = bindings.united(bindingSkipList);
207 types.at(instr.create.type).createInstance(ctxt, bindings, &vmeErrors);
210 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)));
213 QDeclarativeData *ddata = QDeclarativeData::get(o);
216 if (stack.isEmpty()) {
217 if (ddata->context) {
218 Q_ASSERT(ddata->context != ctxt);
219 Q_ASSERT(ddata->outerContext);
220 Q_ASSERT(ddata->outerContext != ctxt);
221 QDeclarativeContextData *c = ddata->context;
222 while (c->linkedContext) c = c->linkedContext;
223 c->linkedContext = ctxt;
228 ddata->ownContext = true;
229 } else if (!ddata->context) {
233 ddata->setImplicitDestructible();
234 ddata->outerContext = ctxt;
235 ddata->lineNumber = instr.line;
236 ddata->columnNumber = instr.create.column;
238 if (instr.create.data != -1) {
239 QDeclarativeCustomParser *customParser =
240 types.at(instr.create.type).type->customParser();
241 customParser->setCustomData(o, datas.at(instr.create.data));
243 if (!stack.isEmpty()) {
244 QObject *parent = stack.top();
245 if (o->isWidgetType()) {
246 QWidget *widget = static_cast<QWidget*>(o);
247 if (parent->isWidgetType()) {
248 QWidget *parentWidget = static_cast<QWidget*>(parent);
249 widget->setParent(parentWidget);
251 // TODO: parent might be a layout
254 QDeclarative_setParent_noEvent(o, parent);
261 case QDeclarativeInstruction::CreateSimpleObject:
263 QObject *o = (QObject *)operator new(instr.createSimple.typeSize +
264 sizeof(QDeclarativeData));
265 ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeData));
266 instr.createSimple.create(o);
268 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize);
269 const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.createSimple.type);
270 if (!ddata->propertyCache && ref.typePropertyCache) {
271 ddata->propertyCache = ref.typePropertyCache;
272 ddata->propertyCache->addref();
274 ddata->lineNumber = instr.line;
275 ddata->columnNumber = instr.createSimple.column;
277 QObjectPrivate::get(o)->declarativeData = ddata;
278 ddata->context = ddata->outerContext = ctxt;
279 ddata->nextContextObject = ctxt->contextObjects;
280 if (ddata->nextContextObject)
281 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
282 ddata->prevContextObject = &ctxt->contextObjects;
283 ctxt->contextObjects = ddata;
285 QObject *parent = stack.top();
286 QDeclarative_setParent_noEvent(o, parent);
292 case QDeclarativeInstruction::SetId:
294 QObject *target = stack.top();
295 ctxt->setIdProperty(instr.setId.index, target);
300 case QDeclarativeInstruction::SetDefault:
302 ctxt->contextObject = stack.top();
306 case QDeclarativeInstruction::CreateComponent:
308 QDeclarativeComponent *qcomp =
309 new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count,
310 stack.isEmpty() ? 0 : stack.top());
312 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
315 ctxt->addObject(qcomp);
318 ddata->ownContext = true;
320 ddata->setImplicitDestructible();
321 ddata->outerContext = ctxt;
322 ddata->lineNumber = instr.line;
323 ddata->columnNumber = instr.create.column;
325 QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
328 ii += instr.createComponent.count;
332 case QDeclarativeInstruction::StoreMetaObject:
334 QObject *target = stack.top();
337 const QByteArray &metadata = datas.at(instr.storeMeta.data);
338 QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
340 const QDeclarativeVMEMetaData *data =
341 (const QDeclarativeVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
343 (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
345 if (instr.storeMeta.propertyCache != -1) {
346 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
347 if (ddata->propertyCache) ddata->propertyCache->release();
348 ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache);
349 ddata->propertyCache->addref();
354 case QDeclarativeInstruction::StoreVariant:
356 QObject *target = stack.top();
357 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
359 // XXX - can be more efficient
360 QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.storeString.value));
361 void *a[] = { &v, 0, &status, &flags };
362 QMetaObject::metacall(target, QMetaObject::WriteProperty,
363 instr.storeString.propertyIndex, a);
367 case QDeclarativeInstruction::StoreVariantInteger:
369 QObject *target = stack.top();
370 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
372 QVariant v(instr.storeInteger.value);
373 void *a[] = { &v, 0, &status, &flags };
374 QMetaObject::metacall(target, QMetaObject::WriteProperty,
375 instr.storeString.propertyIndex, a);
379 case QDeclarativeInstruction::StoreVariantDouble:
381 QObject *target = stack.top();
382 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
384 QVariant v(instr.storeDouble.value);
385 void *a[] = { &v, 0, &status, &flags };
386 QMetaObject::metacall(target, QMetaObject::WriteProperty,
387 instr.storeString.propertyIndex, a);
391 case QDeclarativeInstruction::StoreVariantBool:
393 QObject *target = stack.top();
394 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
396 QVariant v(instr.storeBool.value);
397 void *a[] = { &v, 0, &status, &flags };
398 QMetaObject::metacall(target, QMetaObject::WriteProperty,
399 instr.storeString.propertyIndex, a);
403 case QDeclarativeInstruction::StoreString:
405 QObject *target = stack.top();
406 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
408 void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags };
409 QMetaObject::metacall(target, QMetaObject::WriteProperty,
410 instr.storeString.propertyIndex, a);
414 case QDeclarativeInstruction::StoreByteArray:
416 QObject *target = stack.top();
417 void *a[] = { (void *)&datas.at(instr.storeByteArray.value), 0, &status, &flags };
418 QMetaObject::metacall(target, QMetaObject::WriteProperty,
419 instr.storeByteArray.propertyIndex, a);
423 case QDeclarativeInstruction::StoreUrl:
425 QObject *target = stack.top();
426 CLEAN_PROPERTY(target, instr.storeUrl.propertyIndex);
428 void *a[] = { (void *)&urls.at(instr.storeUrl.value), 0, &status, &flags };
429 QMetaObject::metacall(target, QMetaObject::WriteProperty,
430 instr.storeUrl.propertyIndex, a);
434 case QDeclarativeInstruction::StoreFloat:
436 QObject *target = stack.top();
437 CLEAN_PROPERTY(target, instr.storeFloat.propertyIndex);
439 float f = instr.storeFloat.value;
440 void *a[] = { &f, 0, &status, &flags };
441 QMetaObject::metacall(target, QMetaObject::WriteProperty,
442 instr.storeFloat.propertyIndex, a);
446 case QDeclarativeInstruction::StoreDouble:
448 QObject *target = stack.top();
449 CLEAN_PROPERTY(target, instr.storeDouble.propertyIndex);
451 double d = instr.storeDouble.value;
452 void *a[] = { &d, 0, &status, &flags };
453 QMetaObject::metacall(target, QMetaObject::WriteProperty,
454 instr.storeDouble.propertyIndex, a);
458 case QDeclarativeInstruction::StoreBool:
460 QObject *target = stack.top();
461 CLEAN_PROPERTY(target, instr.storeBool.propertyIndex);
463 void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags };
464 QMetaObject::metacall(target, QMetaObject::WriteProperty,
465 instr.storeBool.propertyIndex, a);
469 case QDeclarativeInstruction::StoreInteger:
471 QObject *target = stack.top();
472 CLEAN_PROPERTY(target, instr.storeInteger.propertyIndex);
474 void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags };
475 QMetaObject::metacall(target, QMetaObject::WriteProperty,
476 instr.storeInteger.propertyIndex, a);
480 case QDeclarativeInstruction::StoreColor:
482 QObject *target = stack.top();
483 CLEAN_PROPERTY(target, instr.storeColor.propertyIndex);
485 QColor c = QColor::fromRgba(instr.storeColor.value);
486 void *a[] = { &c, 0, &status, &flags };
487 QMetaObject::metacall(target, QMetaObject::WriteProperty,
488 instr.storeColor.propertyIndex, a);
492 case QDeclarativeInstruction::StoreDate:
494 QObject *target = stack.top();
495 CLEAN_PROPERTY(target, instr.storeDate.propertyIndex);
497 QDate d = QDate::fromJulianDay(instr.storeDate.value);
498 void *a[] = { &d, 0, &status, &flags };
499 QMetaObject::metacall(target, QMetaObject::WriteProperty,
500 instr.storeDate.propertyIndex, a);
504 case QDeclarativeInstruction::StoreTime:
506 QObject *target = stack.top();
507 CLEAN_PROPERTY(target, instr.storeTime.propertyIndex);
510 t.setHMS(intData.at(instr.storeTime.valueIndex),
511 intData.at(instr.storeTime.valueIndex+1),
512 intData.at(instr.storeTime.valueIndex+2),
513 intData.at(instr.storeTime.valueIndex+3));
514 void *a[] = { &t, 0, &status, &flags };
515 QMetaObject::metacall(target, QMetaObject::WriteProperty,
516 instr.storeTime.propertyIndex, a);
520 case QDeclarativeInstruction::StoreDateTime:
522 QObject *target = stack.top();
523 CLEAN_PROPERTY(target, instr.storeDateTime.propertyIndex);
526 t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
527 intData.at(instr.storeDateTime.valueIndex+2),
528 intData.at(instr.storeDateTime.valueIndex+3),
529 intData.at(instr.storeDateTime.valueIndex+4));
530 QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
531 void *a[] = { &dt, 0, &status, &flags };
532 QMetaObject::metacall(target, QMetaObject::WriteProperty,
533 instr.storeDateTime.propertyIndex, a);
537 case QDeclarativeInstruction::StorePoint:
539 QObject *target = stack.top();
540 CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
542 QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
543 floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
544 void *a[] = { &p, 0, &status, &flags };
545 QMetaObject::metacall(target, QMetaObject::WriteProperty,
546 instr.storeRealPair.propertyIndex, a);
550 case QDeclarativeInstruction::StorePointF:
552 QObject *target = stack.top();
553 CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
555 QPointF p(floatData.at(instr.storeRealPair.valueIndex),
556 floatData.at(instr.storeRealPair.valueIndex+1));
557 void *a[] = { &p, 0, &status, &flags };
558 QMetaObject::metacall(target, QMetaObject::WriteProperty,
559 instr.storeRealPair.propertyIndex, a);
563 case QDeclarativeInstruction::StoreSize:
565 QObject *target = stack.top();
566 CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
568 QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
569 floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
570 void *a[] = { &p, 0, &status, &flags };
571 QMetaObject::metacall(target, QMetaObject::WriteProperty,
572 instr.storeRealPair.propertyIndex, a);
576 case QDeclarativeInstruction::StoreSizeF:
578 QObject *target = stack.top();
579 CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
581 QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
582 floatData.at(instr.storeRealPair.valueIndex+1));
583 void *a[] = { &s, 0, &status, &flags };
584 QMetaObject::metacall(target, QMetaObject::WriteProperty,
585 instr.storeRealPair.propertyIndex, a);
589 case QDeclarativeInstruction::StoreRect:
591 QObject *target = stack.top();
592 CLEAN_PROPERTY(target, instr.storeRect.propertyIndex);
594 QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
595 floatData.at(instr.storeRect.valueIndex+1),
596 floatData.at(instr.storeRect.valueIndex+2),
597 floatData.at(instr.storeRect.valueIndex+3)).toRect();
598 void *a[] = { &r, 0, &status, &flags };
599 QMetaObject::metacall(target, QMetaObject::WriteProperty,
600 instr.storeRect.propertyIndex, a);
604 case QDeclarativeInstruction::StoreRectF:
606 QObject *target = stack.top();
607 CLEAN_PROPERTY(target, instr.storeRect.propertyIndex);
609 QRectF r(floatData.at(instr.storeRect.valueIndex),
610 floatData.at(instr.storeRect.valueIndex+1),
611 floatData.at(instr.storeRect.valueIndex+2),
612 floatData.at(instr.storeRect.valueIndex+3));
613 void *a[] = { &r, 0, &status, &flags };
614 QMetaObject::metacall(target, QMetaObject::WriteProperty,
615 instr.storeRect.propertyIndex, a);
619 case QDeclarativeInstruction::StoreVector3D:
621 QObject *target = stack.top();
622 CLEAN_PROPERTY(target, instr.storeVector3D.propertyIndex);
624 QVector3D p(floatData.at(instr.storeVector3D.valueIndex),
625 floatData.at(instr.storeVector3D.valueIndex+1),
626 floatData.at(instr.storeVector3D.valueIndex+2));
627 void *a[] = { &p, 0, &status, &flags };
628 QMetaObject::metacall(target, QMetaObject::WriteProperty,
629 instr.storeVector3D.propertyIndex, a);
633 case QDeclarativeInstruction::StoreObject:
635 QObject *assignObj = stack.pop();
636 QObject *target = stack.top();
637 CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
639 void *a[] = { (void *)&assignObj, 0, &status, &flags };
640 QMetaObject::metacall(target, QMetaObject::WriteProperty,
641 instr.storeObject.propertyIndex, a);
646 case QDeclarativeInstruction::AssignCustomType:
648 QObject *target = stack.top();
649 CLEAN_PROPERTY(target, instr.assignCustomType.propertyIndex);
651 QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
652 const QString &primitive = primitives.at(data.index);
653 QDeclarativeMetaType::StringConverter converter =
654 QDeclarativeMetaType::customStringConverter(data.type);
655 QVariant v = (*converter)(primitive);
658 target->metaObject()->property(instr.assignCustomType.propertyIndex);
659 if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
660 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())));
662 void *a[] = { (void *)v.data(), 0, &status, &flags };
663 QMetaObject::metacall(target, QMetaObject::WriteProperty,
664 instr.assignCustomType.propertyIndex, a);
668 case QDeclarativeInstruction::AssignSignalObject:
672 QObject *assign = stack.pop();
673 QObject *target = stack.top();
674 int sigIdx = instr.assignSignalObject.signal;
675 const QByteArray &pr = datas.at(sigIdx);
677 QDeclarativeProperty prop(target, QString::fromUtf8(pr));
678 if (prop.type() & QDeclarativeProperty::SignalProperty) {
680 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
681 if (method.signature() == 0)
682 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())));
684 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
685 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())));
687 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
690 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)));
697 case QDeclarativeInstruction::StoreSignal:
699 QObject *target = stack.top();
700 QObject *context = stack.at(stack.count() - 1 - instr.storeSignal.context);
702 QMetaMethod signal = target->metaObject()->method(instr.storeSignal.signalIndex);
704 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
705 QDeclarativeExpression *expr =
706 new QDeclarativeExpression(ctxt, context, primitives.at(instr.storeSignal.value));
707 expr->setSourceLocation(comp->name, instr.line);
708 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.storeSignal.name);
709 bs->setExpression(expr);
713 case QDeclarativeInstruction::StoreImportedScript:
715 ctxt->importedScripts << run(ctxt, scripts.at(instr.storeScript.value));
719 case QDeclarativeInstruction::StoreScriptString:
721 QObject *target = stack.top();
722 QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope);
723 QDeclarativeScriptString ss;
724 ss.setContext(ctxt->asQDeclarativeContext());
725 ss.setScopeObject(scope);
726 ss.setScript(primitives.at(instr.storeScriptString.value));
728 void *a[] = { &ss, 0, &status, &flags };
729 QMetaObject::metacall(target, QMetaObject::WriteProperty,
730 instr.storeScriptString.propertyIndex, a);
734 case QDeclarativeInstruction::BeginObject:
736 QObject *target = stack.top();
737 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
738 parserStatus.append(status);
739 status->d = &parserStatus.values[parserStatus.count - 1];
741 status->classBegin();
745 case QDeclarativeInstruction::StoreBinding:
746 case QDeclarativeInstruction::StoreBindingOnAlias:
749 stack.at(stack.count() - 1 - instr.assignBinding.owner);
751 stack.at(stack.count() - 1 - instr.assignBinding.context);
753 QDeclarativeProperty mp =
754 QDeclarativePropertyPrivate::restore(datas.at(instr.assignBinding.property), target, ctxt);
756 int coreIndex = mp.index();
758 if ((stack.count() - instr.assignBinding.owner) == 1 && bindingSkipList.testBit(coreIndex))
761 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
762 bindValues.append(bind);
763 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
766 if (instr.type == QDeclarativeInstruction::StoreBindingOnAlias) {
767 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
768 if (old) { old->destroy(); }
770 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
775 case QDeclarativeInstruction::StoreCompiledBinding:
778 stack.at(stack.count() - 1 - instr.assignBinding.owner);
780 stack.at(stack.count() - 1 - instr.assignBinding.context);
782 int property = instr.assignBinding.property;
783 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
786 QDeclarativeAbstractBinding *binding =
787 ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property);
788 bindValues.append(binding);
789 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
790 binding->addToObject(target, property);
794 case QDeclarativeInstruction::StoreValueSource:
796 QObject *obj = stack.pop();
797 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.assignValueSource.castValue);
798 QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner);
800 QDeclarativeProperty prop =
801 QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueSource.property), target, ctxt);
802 obj->setParent(target);
807 case QDeclarativeInstruction::StoreValueInterceptor:
809 QObject *obj = stack.pop();
810 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue);
811 QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner);
812 QDeclarativeProperty prop =
813 QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueInterceptor.property), target, ctxt);
814 obj->setParent(target);
816 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
817 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
821 case QDeclarativeInstruction::StoreObjectQList:
823 QObject *assign = stack.pop();
825 const ListInstance &list = qliststack.top();
826 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
830 case QDeclarativeInstruction::AssignObjectList:
832 // This is only used for assigning interfaces
833 QObject *assign = stack.pop();
834 const ListInstance &list = qliststack.top();
836 int type = list.type;
840 const char *iid = QDeclarativeMetaType::interfaceIId(type);
842 ptr = assign->qt_metacast(iid);
844 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"));
847 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
851 case QDeclarativeInstruction::StoreVariantObject:
853 QObject *assign = stack.pop();
854 QObject *target = stack.top();
855 CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
857 QVariant v = QVariant::fromValue(assign);
858 void *a[] = { &v, 0, &status, &flags };
859 QMetaObject::metacall(target, QMetaObject::WriteProperty,
860 instr.storeObject.propertyIndex, a);
864 case QDeclarativeInstruction::StoreInterface:
866 QObject *assign = stack.pop();
867 QObject *target = stack.top();
868 CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
870 int coreIdx = instr.storeObject.propertyIndex;
871 QMetaProperty prop = target->metaObject()->property(coreIdx);
872 int t = prop.userType();
873 const char *iid = QDeclarativeMetaType::interfaceIId(t);
876 void *ptr = assign->qt_metacast(iid);
878 void *a[] = { &ptr, 0, &status, &flags };
879 QMetaObject::metacall(target,
880 QMetaObject::WriteProperty,
887 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"));
891 case QDeclarativeInstruction::FetchAttached:
893 QObject *target = stack.top();
895 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target);
898 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"));
900 stack.push(qmlObject);
904 case QDeclarativeInstruction::FetchQList:
906 QObject *target = stack.top();
908 qliststack.push(ListInstance(instr.fetchQmlList.type));
911 a[0] = (void *)&(qliststack.top().qListProperty);
912 QMetaObject::metacall(target, QMetaObject::ReadProperty,
913 instr.fetchQmlList.property, a);
917 case QDeclarativeInstruction::FetchObject:
919 QObject *target = stack.top();
922 // NOTE: This assumes a cast to QObject does not alter the
926 QMetaObject::metacall(target, QMetaObject::ReadProperty,
927 instr.fetch.property, a);
930 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name())));
936 case QDeclarativeInstruction::PopQList:
942 case QDeclarativeInstruction::Defer:
944 if (instr.defer.deferCount) {
945 QObject *target = stack.top();
946 QDeclarativeData *data =
947 QDeclarativeData::get(target, true);
949 data->deferredComponent = comp;
950 data->deferredIdx = ii;
951 ii += instr.defer.deferCount;
956 case QDeclarativeInstruction::PopFetchedObject:
962 case QDeclarativeInstruction::FetchValueType:
964 QObject *target = stack.top();
966 if (instr.fetchValue.bindingSkipList != 0) {
967 // Possibly need to clear bindings
968 QDeclarativeData *targetData = QDeclarativeData::get(target);
970 QDeclarativeAbstractBinding *binding =
971 QDeclarativePropertyPrivate::binding(target, instr.fetchValue.property, -1);
973 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
974 QDeclarativePropertyPrivate::setBinding(target, instr.fetchValue.property, -1, 0);
976 } else if (binding) {
977 QDeclarativeValueTypeProxyBinding *proxy =
978 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
979 proxy->removeBindings(instr.fetchValue.bindingSkipList);
984 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.fetchValue.type];
985 valueHandler->read(target, instr.fetchValue.property);
986 stack.push(valueHandler);
990 case QDeclarativeInstruction::PopValueType:
992 QDeclarativeValueType *valueHandler =
993 static_cast<QDeclarativeValueType *>(stack.pop());
994 QObject *target = stack.top();
995 valueHandler->write(target, instr.fetchValue.property,
996 QDeclarativePropertyPrivate::BypassInterceptor);
1001 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", instr.type);
1007 if (!stack.isEmpty()) {
1008 delete stack.at(0); // ### What about failures in deferred creation?
1013 QDeclarativeEnginePrivate::clear(bindValues);
1014 QDeclarativeEnginePrivate::clear(parserStatus);
1018 if (bindValues.count)
1019 ep->bindValues << bindValues;
1020 else if (bindValues.values)
1023 if (parserStatus.count)
1024 ep->parserStatus << parserStatus;
1025 else if (parserStatus.values)
1026 parserStatus.clear();
1028 Q_ASSERT(stack.count() == 1);
1032 bool QDeclarativeVME::isError() const
1034 return !vmeErrors.isEmpty();
1037 QList<QDeclarativeError> QDeclarativeVME::errors() const
1043 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
1044 const QBitField &bindings,
1045 QList<QDeclarativeError> *errors) const
1051 type->create(&rv, &memory, sizeof(QDeclarativeData));
1052 QDeclarativeData *ddata = new (memory) QDeclarativeData;
1053 ddata->ownMemory = false;
1054 QObjectPrivate::get(rv)->declarativeData = ddata;
1056 if (typePropertyCache && !ddata->propertyCache) {
1057 ddata->propertyCache = typePropertyCache;
1058 ddata->propertyCache->addref();
1063 Q_ASSERT(component);
1064 return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, -1, 0, errors, bindings);
1068 QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1070 if (script->m_loaded)
1071 return script->m_value;
1073 QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1074 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine);
1076 bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
1078 // Create the script context if required
1079 QDeclarativeContextData *ctxt = 0;
1081 ctxt = new QDeclarativeContextData;
1082 ctxt->isInternal = true;
1083 ctxt->url = script->url;
1085 // For backward compatibility, if there are no imports, we need to use the
1086 // imports from the parent context. See QTBUG-17518.
1087 if (!script->importCache->isEmpty()) {
1088 ctxt->imports = script->importCache;
1090 ctxt->imports = parentCtxt->imports;
1093 if (ctxt->imports) {
1094 ctxt->imports->addref();
1097 ctxt->setParent(parentCtxt, true);
1099 for (int ii = 0; ii < script->scripts.count(); ++ii)
1100 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1103 QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
1105 scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()?
1107 scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString()));
1110 scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
1111 QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
1112 scriptContext->pushScope(scope);
1114 scriptEngine->evaluate(script->m_program);
1116 if (scriptEngine->hasUncaughtException()) {
1117 QDeclarativeError error;
1118 QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
1119 enginePriv->warning(error);
1122 scriptEngine->popContext();
1125 script->m_loaded = true;
1126 script->m_value = scope;