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, line) \
85 QDeclarativeError error; \
86 error.setDescription(desc.trimmed()); \
87 error.setLine(line); \
88 error.setUrl(comp->url); \
101 QDeclarativeListProperty<void> qListProperty;
104 QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp,
105 int start, const QBitField &bindingSkipList)
107 QDeclarativeVMEStack<QObject *> stack;
109 if (start == -1) start = 0;
111 return run(stack, ctxt, comp, start, bindingSkipList);
114 void QDeclarativeVME::runDeferred(QObject *object)
116 QDeclarativeData *data = QDeclarativeData::get(object);
118 if (!data || !data->context || !data->deferredComponent)
121 QDeclarativeContextData *ctxt = data->context;
122 QDeclarativeCompiledData *comp = data->deferredComponent;
123 int start = data->deferredIdx;
124 QDeclarativeVMEStack<QObject *> stack;
127 run(stack, ctxt, comp, start, QBitField());
130 inline bool fastHasBinding(QObject *o, int index)
132 QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
134 return ddata && (ddata->bindingBitsSize > index) &&
135 (ddata->bindingBits[index / 32] & (1 << (index % 32)));
138 static void removeBindingOnProperty(QObject *o, int index)
140 QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
141 if (binding) binding->destroy();
144 #define QML_BEGIN_INSTR(I) \
145 case QDeclarativeInstruction::I: { \
146 const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(genericInstr); \
147 instructionStream += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \
150 #define QML_END_INSTR(I) } break;
152 #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
154 QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
155 QDeclarativeContextData *ctxt,
156 QDeclarativeCompiledData *comp,
157 int start, const QBitField &bindingSkipList)
161 const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types;
162 const QList<QString> &primitives = comp->primitives;
163 const QList<QByteArray> &datas = comp->datas;
164 const QList<QDeclarativeCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
165 const QList<int> &intData = comp->intData;
166 const QList<float> &floatData = comp->floatData;
167 const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches;
168 const QList<QDeclarativeScriptData *> &scripts = comp->scripts;
169 const QList<QUrl> &urls = comp->urls;
171 QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues;
172 QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus;
174 QDeclarativeVMEStack<ListInstance> qliststack;
177 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
179 int status = -1; //for dbus
180 QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
181 QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
183 const char *instructionStream = comp->bytecode.constData() + start;
186 while (!isError() && !done) {
187 const QDeclarativeInstruction &genericInstr = *((QDeclarativeInstruction *)instructionStream);
189 switch(genericInstr.type()) {
190 QML_BEGIN_INSTR(Init)
191 if (instr.bindingsSize)
192 bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.bindingsSize);
193 if (instr.parserStatusSize)
194 parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.parserStatusSize);
195 if (instr.contextCache != -1)
196 ctxt->setIdPropertyData(comp->contextCaches.at(instr.contextCache));
197 if (instr.compiledBinding != -1)
198 ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.compiledBinding).constData(), ctxt);
201 QML_BEGIN_INSTR(Done)
205 QML_BEGIN_INSTR(CreateObject)
207 if (instr.bindingBits != -1) {
208 const QByteArray &bits = datas.at(instr.bindingBits);
209 bindings = QBitField((const quint32*)bits.constData(),
213 bindings = bindings.united(bindingSkipList);
216 types.at(instr.type).createInstance(ctxt, bindings, &vmeErrors);
219 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.type).className)), instr.line);
222 QDeclarativeData *ddata = QDeclarativeData::get(o);
225 if (stack.isEmpty()) {
226 if (ddata->context) {
227 Q_ASSERT(ddata->context != ctxt);
228 Q_ASSERT(ddata->outerContext);
229 Q_ASSERT(ddata->outerContext != ctxt);
230 QDeclarativeContextData *c = ddata->context;
231 while (c->linkedContext) c = c->linkedContext;
232 c->linkedContext = ctxt;
237 ddata->ownContext = true;
238 } else if (!ddata->context) {
242 ddata->setImplicitDestructible();
243 ddata->outerContext = ctxt;
244 ddata->lineNumber = instr.line;
245 ddata->columnNumber = instr.column;
247 if (instr.data != -1) {
248 QDeclarativeCustomParser *customParser =
249 types.at(instr.type).type->customParser();
250 customParser->setCustomData(o, datas.at(instr.data));
252 if (!stack.isEmpty()) {
253 QObject *parent = stack.top();
254 if (o->isWidgetType()) {
255 QWidget *widget = static_cast<QWidget*>(o);
256 if (parent->isWidgetType()) {
257 QWidget *parentWidget = static_cast<QWidget*>(parent);
258 widget->setParent(parentWidget);
260 // TODO: parent might be a layout
263 QDeclarative_setParent_noEvent(o, parent);
267 QML_END_INSTR(CreateObject)
269 QML_BEGIN_INSTR(CreateSimpleObject)
270 QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));
271 ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
274 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
275 const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.type);
276 if (!ddata->propertyCache && ref.typePropertyCache) {
277 ddata->propertyCache = ref.typePropertyCache;
278 ddata->propertyCache->addref();
280 ddata->lineNumber = instr.line;
281 ddata->columnNumber = instr.column;
283 QObjectPrivate::get(o)->declarativeData = ddata;
284 ddata->context = ddata->outerContext = ctxt;
285 ddata->nextContextObject = ctxt->contextObjects;
286 if (ddata->nextContextObject)
287 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
288 ddata->prevContextObject = &ctxt->contextObjects;
289 ctxt->contextObjects = ddata;
291 QObject *parent = stack.top();
292 QDeclarative_setParent_noEvent(o, parent);
295 QML_END_INSTR(CreateSimpleObject)
297 QML_BEGIN_INSTR(SetId)
298 QObject *target = stack.top();
299 ctxt->setIdProperty(instr.index, target);
302 QML_BEGIN_INSTR(SetDefault)
303 ctxt->contextObject = stack.top();
304 QML_END_INSTR(SetDefault)
306 QML_BEGIN_INSTR(CreateComponent)
307 QDeclarativeComponent *qcomp =
308 new QDeclarativeComponent(ctxt->engine, comp, instructionStream - comp->bytecode.constData(),
309 stack.isEmpty() ? 0 : stack.top());
311 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
314 ctxt->addObject(qcomp);
317 ddata->ownContext = true;
319 ddata->setImplicitDestructible();
320 ddata->outerContext = ctxt;
321 ddata->lineNumber = instr.line;
322 ddata->columnNumber = instr.column;
324 QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
327 instructionStream += instr.count;
328 QML_END_INSTR(CreateComponent)
330 QML_BEGIN_INSTR(StoreMetaObject)
331 QObject *target = stack.top();
334 const QByteArray &metadata = datas.at(instr.data);
335 QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
337 const QDeclarativeVMEMetaData *data =
338 (const QDeclarativeVMEMetaData *)datas.at(instr.aliasData).constData();
340 (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
342 if (instr.propertyCache != -1) {
343 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
344 if (ddata->propertyCache) ddata->propertyCache->release();
345 ddata->propertyCache = propertyCaches.at(instr.propertyCache);
346 ddata->propertyCache->addref();
348 QML_END_INSTR(StoreMetaObject)
350 QML_BEGIN_INSTR(StoreVariant)
351 QObject *target = stack.top();
352 CLEAN_PROPERTY(target, instr.propertyIndex);
354 // XXX - can be more efficient
355 QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.value));
356 void *a[] = { &v, 0, &status, &flags };
357 QMetaObject::metacall(target, QMetaObject::WriteProperty,
358 instr.propertyIndex, a);
359 QML_END_INSTR(StoreVariant)
361 QML_BEGIN_INSTR(StoreVariantInteger)
362 QObject *target = stack.top();
363 CLEAN_PROPERTY(target, instr.propertyIndex);
365 QVariant v(instr.value);
366 void *a[] = { &v, 0, &status, &flags };
367 QMetaObject::metacall(target, QMetaObject::WriteProperty,
368 instr.propertyIndex, a);
369 QML_END_INSTR(StoreVariantInteger)
371 QML_BEGIN_INSTR(StoreVariantDouble)
372 QObject *target = stack.top();
373 CLEAN_PROPERTY(target, instr.propertyIndex);
375 QVariant v(instr.value);
376 void *a[] = { &v, 0, &status, &flags };
377 QMetaObject::metacall(target, QMetaObject::WriteProperty,
378 instr.propertyIndex, a);
379 QML_END_INSTR(StoreVariantDouble)
381 QML_BEGIN_INSTR(StoreVariantBool)
382 QObject *target = stack.top();
383 CLEAN_PROPERTY(target, instr.propertyIndex);
385 QVariant v(instr.value);
386 void *a[] = { &v, 0, &status, &flags };
387 QMetaObject::metacall(target, QMetaObject::WriteProperty,
388 instr.propertyIndex, a);
389 QML_END_INSTR(StoreVariantBool)
391 QML_BEGIN_INSTR(StoreString)
392 QObject *target = stack.top();
393 CLEAN_PROPERTY(target, instr.propertyIndex);
395 void *a[] = { (void *)&primitives.at(instr.value), 0, &status, &flags };
396 QMetaObject::metacall(target, QMetaObject::WriteProperty,
397 instr.propertyIndex, a);
398 QML_END_INSTR(StoreString)
400 QML_BEGIN_INSTR(StoreByteArray)
401 QObject *target = stack.top();
402 void *a[] = { (void *)&datas.at(instr.value), 0, &status, &flags };
403 QMetaObject::metacall(target, QMetaObject::WriteProperty,
404 instr.propertyIndex, a);
405 QML_END_INSTR(StoreByteArray)
407 QML_BEGIN_INSTR(StoreUrl)
408 QObject *target = stack.top();
409 CLEAN_PROPERTY(target, instr.propertyIndex);
411 void *a[] = { (void *)&urls.at(instr.value), 0, &status, &flags };
412 QMetaObject::metacall(target, QMetaObject::WriteProperty,
413 instr.propertyIndex, a);
414 QML_END_INSTR(StoreUrl)
416 QML_BEGIN_INSTR(StoreFloat)
417 QObject *target = stack.top();
418 CLEAN_PROPERTY(target, instr.propertyIndex);
420 float f = instr.value;
421 void *a[] = { &f, 0, &status, &flags };
422 QMetaObject::metacall(target, QMetaObject::WriteProperty,
423 instr.propertyIndex, a);
424 QML_END_INSTR(StoreFloat)
426 QML_BEGIN_INSTR(StoreDouble)
427 QObject *target = stack.top();
428 CLEAN_PROPERTY(target, instr.propertyIndex);
430 double d = instr.value;
431 void *a[] = { &d, 0, &status, &flags };
432 QMetaObject::metacall(target, QMetaObject::WriteProperty,
433 instr.propertyIndex, a);
434 QML_END_INSTR(StoreDouble)
436 QML_BEGIN_INSTR(StoreBool)
437 QObject *target = stack.top();
438 CLEAN_PROPERTY(target, instr.propertyIndex);
440 void *a[] = { (void *)&instr.value, 0, &status, &flags };
441 QMetaObject::metacall(target, QMetaObject::WriteProperty,
442 instr.propertyIndex, a);
443 QML_END_INSTR(StoreBool)
445 QML_BEGIN_INSTR(StoreInteger)
446 QObject *target = stack.top();
447 CLEAN_PROPERTY(target, instr.propertyIndex);
449 void *a[] = { (void *)&instr.value, 0, &status, &flags };
450 QMetaObject::metacall(target, QMetaObject::WriteProperty,
451 instr.propertyIndex, a);
452 QML_END_INSTR(StoreInteger)
454 QML_BEGIN_INSTR(StoreColor)
455 QObject *target = stack.top();
456 CLEAN_PROPERTY(target, instr.propertyIndex);
458 QColor c = QColor::fromRgba(instr.value);
459 void *a[] = { &c, 0, &status, &flags };
460 QMetaObject::metacall(target, QMetaObject::WriteProperty,
461 instr.propertyIndex, a);
462 QML_END_INSTR(StoreColor)
464 QML_BEGIN_INSTR(StoreDate)
465 QObject *target = stack.top();
466 CLEAN_PROPERTY(target, instr.propertyIndex);
468 QDate d = QDate::fromJulianDay(instr.value);
469 void *a[] = { &d, 0, &status, &flags };
470 QMetaObject::metacall(target, QMetaObject::WriteProperty,
471 instr.propertyIndex, a);
472 QML_END_INSTR(StoreDate)
474 QML_BEGIN_INSTR(StoreTime)
475 QObject *target = stack.top();
476 CLEAN_PROPERTY(target, instr.propertyIndex);
479 t.setHMS(intData.at(instr.valueIndex),
480 intData.at(instr.valueIndex+1),
481 intData.at(instr.valueIndex+2),
482 intData.at(instr.valueIndex+3));
483 void *a[] = { &t, 0, &status, &flags };
484 QMetaObject::metacall(target, QMetaObject::WriteProperty,
485 instr.propertyIndex, a);
486 QML_END_INSTR(StoreTime)
488 QML_BEGIN_INSTR(StoreDateTime)
489 QObject *target = stack.top();
490 CLEAN_PROPERTY(target, instr.propertyIndex);
493 t.setHMS(intData.at(instr.valueIndex+1),
494 intData.at(instr.valueIndex+2),
495 intData.at(instr.valueIndex+3),
496 intData.at(instr.valueIndex+4));
497 QDateTime dt(QDate::fromJulianDay(intData.at(instr.valueIndex)), t);
498 void *a[] = { &dt, 0, &status, &flags };
499 QMetaObject::metacall(target, QMetaObject::WriteProperty,
500 instr.propertyIndex, a);
501 QML_END_INSTR(StoreDateTime)
503 QML_BEGIN_INSTR(StorePoint)
504 QObject *target = stack.top();
505 CLEAN_PROPERTY(target, instr.propertyIndex);
507 QPoint p = QPointF(floatData.at(instr.valueIndex),
508 floatData.at(instr.valueIndex+1)).toPoint();
509 void *a[] = { &p, 0, &status, &flags };
510 QMetaObject::metacall(target, QMetaObject::WriteProperty,
511 instr.propertyIndex, a);
512 QML_END_INSTR(StorePoint)
514 QML_BEGIN_INSTR(StorePointF)
515 QObject *target = stack.top();
516 CLEAN_PROPERTY(target, instr.propertyIndex);
518 QPointF p(floatData.at(instr.valueIndex),
519 floatData.at(instr.valueIndex+1));
520 void *a[] = { &p, 0, &status, &flags };
521 QMetaObject::metacall(target, QMetaObject::WriteProperty,
522 instr.propertyIndex, a);
523 QML_END_INSTR(StorePointF)
525 QML_BEGIN_INSTR(StoreSize)
526 QObject *target = stack.top();
527 CLEAN_PROPERTY(target, instr.propertyIndex);
529 QSize p = QSizeF(floatData.at(instr.valueIndex),
530 floatData.at(instr.valueIndex+1)).toSize();
531 void *a[] = { &p, 0, &status, &flags };
532 QMetaObject::metacall(target, QMetaObject::WriteProperty,
533 instr.propertyIndex, a);
534 QML_END_INSTR(StoreSize)
536 QML_BEGIN_INSTR(StoreSizeF)
537 QObject *target = stack.top();
538 CLEAN_PROPERTY(target, instr.propertyIndex);
540 QSizeF s(floatData.at(instr.valueIndex),
541 floatData.at(instr.valueIndex+1));
542 void *a[] = { &s, 0, &status, &flags };
543 QMetaObject::metacall(target, QMetaObject::WriteProperty,
544 instr.propertyIndex, a);
545 QML_END_INSTR(StoreSizeF)
547 QML_BEGIN_INSTR(StoreRect)
548 QObject *target = stack.top();
549 CLEAN_PROPERTY(target, instr.propertyIndex);
551 QRect r = QRectF(floatData.at(instr.valueIndex),
552 floatData.at(instr.valueIndex+1),
553 floatData.at(instr.valueIndex+2),
554 floatData.at(instr.valueIndex+3)).toRect();
555 void *a[] = { &r, 0, &status, &flags };
556 QMetaObject::metacall(target, QMetaObject::WriteProperty,
557 instr.propertyIndex, a);
558 QML_END_INSTR(StoreRect)
560 QML_BEGIN_INSTR(StoreRectF)
561 QObject *target = stack.top();
562 CLEAN_PROPERTY(target, instr.propertyIndex);
564 QRectF r(floatData.at(instr.valueIndex),
565 floatData.at(instr.valueIndex+1),
566 floatData.at(instr.valueIndex+2),
567 floatData.at(instr.valueIndex+3));
568 void *a[] = { &r, 0, &status, &flags };
569 QMetaObject::metacall(target, QMetaObject::WriteProperty,
570 instr.propertyIndex, a);
571 QML_END_INSTR(StoreRectF)
573 QML_BEGIN_INSTR(StoreVector3D)
574 QObject *target = stack.top();
575 CLEAN_PROPERTY(target, instr.propertyIndex);
577 QVector3D p(floatData.at(instr.valueIndex),
578 floatData.at(instr.valueIndex+1),
579 floatData.at(instr.valueIndex+2));
580 void *a[] = { &p, 0, &status, &flags };
581 QMetaObject::metacall(target, QMetaObject::WriteProperty,
582 instr.propertyIndex, a);
583 QML_END_INSTR(StoreVector3D)
585 QML_BEGIN_INSTR(StoreObject)
586 QObject *assignObj = stack.pop();
587 QObject *target = stack.top();
588 CLEAN_PROPERTY(target, instr.propertyIndex);
590 void *a[] = { (void *)&assignObj, 0, &status, &flags };
591 QMetaObject::metacall(target, QMetaObject::WriteProperty,
592 instr.propertyIndex, a);
593 QML_END_INSTR(StoreObject)
595 QML_BEGIN_INSTR(AssignCustomType)
596 QObject *target = stack.top();
597 CLEAN_PROPERTY(target, instr.propertyIndex);
599 QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.valueIndex);
600 const QString &primitive = primitives.at(data.index);
601 QDeclarativeMetaType::StringConverter converter =
602 QDeclarativeMetaType::customStringConverter(data.type);
603 QVariant v = (*converter)(primitive);
606 target->metaObject()->property(instr.propertyIndex);
607 if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
608 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
610 void *a[] = { (void *)v.data(), 0, &status, &flags };
611 QMetaObject::metacall(target, QMetaObject::WriteProperty,
612 instr.propertyIndex, a);
613 QML_END_INSTR(AssignCustomType)
615 QML_BEGIN_INSTR(AssignSignalObject)
618 QObject *assign = stack.pop();
619 QObject *target = stack.top();
620 int sigIdx = instr.signal;
621 const QByteArray &pr = datas.at(sigIdx);
623 QDeclarativeProperty prop(target, QString::fromUtf8(pr));
624 if (prop.type() & QDeclarativeProperty::SignalProperty) {
626 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
627 if (method.signature() == 0)
628 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
630 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
631 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);
633 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
636 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.line);
640 QML_END_INSTR(AssignSignalObject)
642 QML_BEGIN_INSTR(StoreSignal)
643 QObject *target = stack.top();
644 QObject *context = stack.at(stack.count() - 1 - instr.context);
646 QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
648 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
649 QDeclarativeExpression *expr =
650 new QDeclarativeExpression(ctxt, context, primitives.at(instr.value));
651 expr->setSourceLocation(comp->name, instr.line);
652 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.name);
653 bs->setExpression(expr);
654 QML_END_INSTR(StoreSignal)
656 QML_BEGIN_INSTR(StoreImportedScript)
657 ctxt->importedScripts << run(ctxt, scripts.at(instr.value));
658 QML_END_INSTR(StoreImportedScript)
660 QML_BEGIN_INSTR(StoreScriptString)
661 QObject *target = stack.top();
662 QObject *scope = stack.at(stack.count() - 1 - instr.scope);
663 QDeclarativeScriptString ss;
664 ss.setContext(ctxt->asQDeclarativeContext());
665 ss.setScopeObject(scope);
666 ss.setScript(primitives.at(instr.value));
668 void *a[] = { &ss, 0, &status, &flags };
669 QMetaObject::metacall(target, QMetaObject::WriteProperty,
670 instr.propertyIndex, a);
671 QML_END_INSTR(StoreScriptString)
673 QML_BEGIN_INSTR(BeginObject)
674 QObject *target = stack.top();
675 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
676 parserStatus.append(status);
677 status->d = &parserStatus.values[parserStatus.count - 1];
679 status->classBegin();
680 QML_END_INSTR(BeginObject)
682 QML_BEGIN_INSTR(StoreBinding)
684 stack.at(stack.count() - 1 - instr.owner);
686 stack.at(stack.count() - 1 - instr.context);
688 QDeclarativeProperty mp =
689 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
691 int coreIndex = mp.index();
693 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
696 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
697 bindValues.append(bind);
698 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
701 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
702 QML_END_INSTR(StoreBinding)
704 QML_BEGIN_INSTR(StoreBindingOnAlias)
706 stack.at(stack.count() - 1 - instr.owner);
708 stack.at(stack.count() - 1 - instr.context);
710 QDeclarativeProperty mp =
711 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
713 int coreIndex = mp.index();
715 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
718 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
719 bindValues.append(bind);
720 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
723 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
724 if (old) { old->destroy(); }
725 QML_END_INSTR(StoreBindingOnAlias)
727 QML_BEGIN_INSTR(StoreCompiledBinding)
729 stack.at(stack.count() - 1 - instr.owner);
731 stack.at(stack.count() - 1 - instr.context);
733 int property = instr.property;
734 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
737 QDeclarativeAbstractBinding *binding =
738 ctxt->optimizedBindings->configBinding(instr.value, target, scope, property);
739 bindValues.append(binding);
740 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
741 binding->addToObject(target, property);
742 QML_END_INSTR(StoreCompiledBinding)
744 QML_BEGIN_INSTR(StoreValueSource)
745 QObject *obj = stack.pop();
746 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
747 QObject *target = stack.at(stack.count() - 1 - instr.owner);
749 QDeclarativeProperty prop =
750 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
751 obj->setParent(target);
753 QML_END_INSTR(StoreValueSource)
755 QML_BEGIN_INSTR(StoreValueInterceptor)
756 QObject *obj = stack.pop();
757 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
758 QObject *target = stack.at(stack.count() - 1 - instr.owner);
759 QDeclarativeProperty prop =
760 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
761 obj->setParent(target);
763 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
764 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
765 QML_END_INSTR(StoreValueInterceptor)
767 QML_BEGIN_INSTR(StoreObjectQList)
768 QObject *assign = stack.pop();
770 const ListInstance &list = qliststack.top();
771 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
772 QML_END_INSTR(StoreObjectQList)
774 QML_BEGIN_INSTR(AssignObjectList)
775 // This is only used for assigning interfaces
776 QObject *assign = stack.pop();
777 const ListInstance &list = qliststack.top();
779 int type = list.type;
783 const char *iid = QDeclarativeMetaType::interfaceIId(type);
785 ptr = assign->qt_metacast(iid);
787 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line);
790 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
791 QML_END_INSTR(AssignObjectList)
793 QML_BEGIN_INSTR(StoreVariantObject)
794 QObject *assign = stack.pop();
795 QObject *target = stack.top();
796 CLEAN_PROPERTY(target, instr.propertyIndex);
798 QVariant v = QVariant::fromValue(assign);
799 void *a[] = { &v, 0, &status, &flags };
800 QMetaObject::metacall(target, QMetaObject::WriteProperty,
801 instr.propertyIndex, a);
802 QML_END_INSTR(StoreVariantObject)
804 QML_BEGIN_INSTR(StoreInterface)
805 QObject *assign = stack.pop();
806 QObject *target = stack.top();
807 CLEAN_PROPERTY(target, instr.propertyIndex);
809 int coreIdx = instr.propertyIndex;
810 QMetaProperty prop = target->metaObject()->property(coreIdx);
811 int t = prop.userType();
812 const char *iid = QDeclarativeMetaType::interfaceIId(t);
815 void *ptr = assign->qt_metacast(iid);
817 void *a[] = { &ptr, 0, &status, &flags };
818 QMetaObject::metacall(target,
819 QMetaObject::WriteProperty,
826 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line);
827 QML_END_INSTR(StoreInterface)
829 QML_BEGIN_INSTR(FetchAttached)
830 QObject *target = stack.top();
832 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
835 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line);
837 stack.push(qmlObject);
838 QML_END_INSTR(FetchAttached)
840 QML_BEGIN_INSTR(FetchQList)
841 QObject *target = stack.top();
843 qliststack.push(ListInstance(instr.type));
846 a[0] = (void *)&(qliststack.top().qListProperty);
847 QMetaObject::metacall(target, QMetaObject::ReadProperty,
849 QML_END_INSTR(FetchQList)
851 QML_BEGIN_INSTR(FetchObject)
852 QObject *target = stack.top();
855 // NOTE: This assumes a cast to QObject does not alter the
859 QMetaObject::metacall(target, QMetaObject::ReadProperty,
863 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);
866 QML_END_INSTR(FetchObject)
868 QML_BEGIN_INSTR(PopQList)
870 QML_END_INSTR(PopQList)
872 QML_BEGIN_INSTR(Defer)
873 if (instr.deferCount) {
874 QObject *target = stack.top();
875 QDeclarativeData *data =
876 QDeclarativeData::get(target, true);
878 data->deferredComponent = comp;
879 data->deferredIdx = instructionStream - comp->bytecode.constData();
880 instructionStream += instr.deferCount;
884 QML_BEGIN_INSTR(PopFetchedObject)
886 QML_END_INSTR(PopFetchedObject)
888 QML_BEGIN_INSTR(FetchValueType)
889 QObject *target = stack.top();
891 if (instr.bindingSkipList != 0) {
892 // Possibly need to clear bindings
893 QDeclarativeData *targetData = QDeclarativeData::get(target);
895 QDeclarativeAbstractBinding *binding =
896 QDeclarativePropertyPrivate::binding(target, instr.property, -1);
898 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
899 QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
901 } else if (binding) {
902 QDeclarativeValueTypeProxyBinding *proxy =
903 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
904 proxy->removeBindings(instr.bindingSkipList);
909 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
910 valueHandler->read(target, instr.property);
911 stack.push(valueHandler);
912 QML_END_INSTR(FetchValueType)
914 QML_BEGIN_INSTR(PopValueType)
915 QDeclarativeValueType *valueHandler =
916 static_cast<QDeclarativeValueType *>(stack.pop());
917 QObject *target = stack.top();
918 valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
919 QML_END_INSTR(PopValueType)
922 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type());
928 if (!stack.isEmpty()) {
929 delete stack.at(0); // ### What about failures in deferred creation?
934 QDeclarativeEnginePrivate::clear(bindValues);
935 QDeclarativeEnginePrivate::clear(parserStatus);
939 if (bindValues.count)
940 ep->bindValues << bindValues;
941 else if (bindValues.values)
944 if (parserStatus.count)
945 ep->parserStatus << parserStatus;
946 else if (parserStatus.values)
947 parserStatus.clear();
949 Q_ASSERT(stack.count() == 1);
953 bool QDeclarativeVME::isError() const
955 return !vmeErrors.isEmpty();
958 QList<QDeclarativeError> QDeclarativeVME::errors() const
964 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
965 const QBitField &bindings,
966 QList<QDeclarativeError> *errors) const
972 type->create(&rv, &memory, sizeof(QDeclarativeData));
973 QDeclarativeData *ddata = new (memory) QDeclarativeData;
974 ddata->ownMemory = false;
975 QObjectPrivate::get(rv)->declarativeData = ddata;
977 if (typePropertyCache && !ddata->propertyCache) {
978 ddata->propertyCache = typePropertyCache;
979 ddata->propertyCache->addref();
985 return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings);
989 QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
991 if (script->m_loaded)
992 return script->m_value;
994 QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine);
995 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine);
997 bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
999 // Create the script context if required
1000 QDeclarativeContextData *ctxt = 0;
1002 ctxt = new QDeclarativeContextData;
1003 ctxt->isInternal = true;
1004 ctxt->url = script->url;
1006 // For backward compatibility, if there are no imports, we need to use the
1007 // imports from the parent context. See QTBUG-17518.
1008 if (!script->importCache->isEmpty()) {
1009 ctxt->imports = script->importCache;
1011 ctxt->imports = parentCtxt->imports;
1014 if (ctxt->imports) {
1015 ctxt->imports->addref();
1018 ctxt->setParent(parentCtxt, true);
1020 for (int ii = 0; ii < script->scripts.count(); ++ii)
1021 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1024 QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
1026 scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()?
1028 scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString()));
1031 scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
1032 QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
1033 scriptContext->pushScope(scope);
1035 scriptEngine->evaluate(script->m_program);
1037 if (scriptEngine->hasUncaughtException()) {
1038 QDeclarativeError error;
1039 QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
1040 enginePriv->warning(error);
1043 scriptEngine->popContext();
1046 script->m_loaded = true;
1047 script->m_value = scope;