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 <QtScript/qscriptvalue.h>
80 QDeclarativeVME::QDeclarativeVME()
84 #define VME_EXCEPTION(desc, line) \
86 QDeclarativeError error; \
87 error.setDescription(desc.trimmed()); \
88 error.setLine(line); \
89 error.setUrl(comp->url); \
102 QDeclarativeListProperty<void> qListProperty;
105 QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp,
106 int start, const QBitField &bindingSkipList)
108 QDeclarativeVMEStack<QObject *> stack;
110 if (start == -1) start = 0;
112 return run(stack, ctxt, comp, start, 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;
125 QDeclarativeVMEStack<QObject *> stack;
128 run(stack, ctxt, comp, start, QBitField());
131 inline bool fastHasBinding(QObject *o, int index)
133 QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
135 return ddata && (ddata->bindingBitsSize > index) &&
136 (ddata->bindingBits[index / 32] & (1 << (index % 32)));
139 static void removeBindingOnProperty(QObject *o, int index)
141 QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
142 if (binding) binding->destroy();
145 #define QML_BEGIN_INSTR(I) \
146 case QDeclarativeInstruction::I: { \
147 const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(genericInstr); \
148 instructionStream += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \
151 #define QML_END_INSTR(I) } break;
153 #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
155 QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
156 QDeclarativeContextData *ctxt,
157 QDeclarativeCompiledData *comp,
158 int start, const QBitField &bindingSkipList)
162 const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types;
163 const QList<QString> &primitives = comp->primitives;
164 const QList<QByteArray> &datas = comp->datas;
165 const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches;
166 const QList<QDeclarativeScriptData *> &scripts = comp->scripts;
167 const QList<QUrl> &urls = comp->urls;
169 QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues;
170 QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus;
172 QDeclarativeVMEStack<ListInstance> qliststack;
175 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
177 int status = -1; //for dbus
178 QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
179 QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
181 const char *instructionStream = comp->bytecode.constData() + start;
184 while (!isError() && !done) {
185 const QDeclarativeInstruction &genericInstr = *((QDeclarativeInstruction *)instructionStream);
187 switch(genericInstr.type()) {
188 QML_BEGIN_INSTR(Init)
189 if (instr.bindingsSize)
190 bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.bindingsSize);
191 if (instr.parserStatusSize)
192 parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.parserStatusSize);
193 if (instr.contextCache != -1)
194 ctxt->setIdPropertyData(comp->contextCaches.at(instr.contextCache));
195 if (instr.compiledBinding != -1) {
196 const char *v4data = datas.at(instr.compiledBinding).constData();
197 ctxt->v4bindings = new QDeclarativeV4Bindings(v4data, 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);
478 QTime *t = (QTime *)&instr.time;
479 void *a[] = { t, 0, &status, &flags };
480 QMetaObject::metacall(target, QMetaObject::WriteProperty,
481 instr.propertyIndex, a);
482 QML_END_INSTR(StoreTime)
484 QML_BEGIN_INSTR(StoreDateTime)
485 QObject *target = stack.top();
486 CLEAN_PROPERTY(target, instr.propertyIndex);
488 QTime *t = (QTime *)&instr.time;
489 QDateTime dt(QDate::fromJulianDay(instr.date), *t);
490 void *a[] = { &dt, 0, &status, &flags };
491 QMetaObject::metacall(target, QMetaObject::WriteProperty,
492 instr.propertyIndex, a);
493 QML_END_INSTR(StoreDateTime)
495 QML_BEGIN_INSTR(StorePoint)
496 QObject *target = stack.top();
497 CLEAN_PROPERTY(target, instr.propertyIndex);
499 QPoint *p = (QPoint *)&instr.point;
500 void *a[] = { p, 0, &status, &flags };
501 QMetaObject::metacall(target, QMetaObject::WriteProperty,
502 instr.propertyIndex, a);
503 QML_END_INSTR(StorePoint)
505 QML_BEGIN_INSTR(StorePointF)
506 QObject *target = stack.top();
507 CLEAN_PROPERTY(target, instr.propertyIndex);
509 QPointF *p = (QPointF *)&instr.point;
510 void *a[] = { p, 0, &status, &flags };
511 QMetaObject::metacall(target, QMetaObject::WriteProperty,
512 instr.propertyIndex, a);
513 QML_END_INSTR(StorePointF)
515 QML_BEGIN_INSTR(StoreSize)
516 QObject *target = stack.top();
517 CLEAN_PROPERTY(target, instr.propertyIndex);
519 QSize *s = (QSize *)&instr.size;
520 void *a[] = { s, 0, &status, &flags };
521 QMetaObject::metacall(target, QMetaObject::WriteProperty,
522 instr.propertyIndex, a);
523 QML_END_INSTR(StoreSize)
525 QML_BEGIN_INSTR(StoreSizeF)
526 QObject *target = stack.top();
527 CLEAN_PROPERTY(target, instr.propertyIndex);
529 QSizeF *s = (QSizeF *)&instr.size;
530 void *a[] = { s, 0, &status, &flags };
531 QMetaObject::metacall(target, QMetaObject::WriteProperty,
532 instr.propertyIndex, a);
533 QML_END_INSTR(StoreSizeF)
535 QML_BEGIN_INSTR(StoreRect)
536 QObject *target = stack.top();
537 CLEAN_PROPERTY(target, instr.propertyIndex);
539 QRect *r = (QRect *)&instr.rect;
540 void *a[] = { r, 0, &status, &flags };
541 QMetaObject::metacall(target, QMetaObject::WriteProperty,
542 instr.propertyIndex, a);
543 QML_END_INSTR(StoreRect)
545 QML_BEGIN_INSTR(StoreRectF)
546 QObject *target = stack.top();
547 CLEAN_PROPERTY(target, instr.propertyIndex);
549 QRectF *r = (QRectF *)&instr.rect;
550 void *a[] = { r, 0, &status, &flags };
551 QMetaObject::metacall(target, QMetaObject::WriteProperty,
552 instr.propertyIndex, a);
553 QML_END_INSTR(StoreRectF)
555 QML_BEGIN_INSTR(StoreVector3D)
556 QObject *target = stack.top();
557 CLEAN_PROPERTY(target, instr.propertyIndex);
559 QVector3D *v = (QVector3D *)&instr.vector;
560 void *a[] = { v, 0, &status, &flags };
561 QMetaObject::metacall(target, QMetaObject::WriteProperty,
562 instr.propertyIndex, a);
563 QML_END_INSTR(StoreVector3D)
565 QML_BEGIN_INSTR(StoreObject)
566 QObject *assignObj = stack.pop();
567 QObject *target = stack.top();
568 CLEAN_PROPERTY(target, instr.propertyIndex);
570 void *a[] = { (void *)&assignObj, 0, &status, &flags };
571 QMetaObject::metacall(target, QMetaObject::WriteProperty,
572 instr.propertyIndex, a);
573 QML_END_INSTR(StoreObject)
575 QML_BEGIN_INSTR(AssignCustomType)
576 QObject *target = stack.top();
577 CLEAN_PROPERTY(target, instr.propertyIndex);
579 const QString &primitive = primitives.at(instr.primitive);
580 int type = instr.type;
581 QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
582 QVariant v = (*converter)(primitive);
585 target->metaObject()->property(instr.propertyIndex);
586 if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
587 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
589 void *a[] = { (void *)v.data(), 0, &status, &flags };
590 QMetaObject::metacall(target, QMetaObject::WriteProperty,
591 instr.propertyIndex, a);
592 QML_END_INSTR(AssignCustomType)
594 QML_BEGIN_INSTR(AssignSignalObject)
597 QObject *assign = stack.pop();
598 QObject *target = stack.top();
599 int sigIdx = instr.signal;
600 const QByteArray &pr = datas.at(sigIdx);
602 QDeclarativeProperty prop(target, QString::fromUtf8(pr));
603 if (prop.type() & QDeclarativeProperty::SignalProperty) {
605 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
606 if (method.signature() == 0)
607 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
609 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
610 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);
612 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
615 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.line);
619 QML_END_INSTR(AssignSignalObject)
621 QML_BEGIN_INSTR(StoreSignal)
622 QObject *target = stack.top();
623 QObject *context = stack.at(stack.count() - 1 - instr.context);
625 QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
627 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
628 QDeclarativeExpression *expr =
629 new QDeclarativeExpression(ctxt, context, primitives.at(instr.value));
630 expr->setSourceLocation(comp->name, instr.line);
631 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.name);
632 bs->setExpression(expr);
633 QML_END_INSTR(StoreSignal)
635 QML_BEGIN_INSTR(StoreImportedScript)
636 ctxt->importedScripts << run(ctxt, scripts.at(instr.value));
637 QML_END_INSTR(StoreImportedScript)
639 QML_BEGIN_INSTR(StoreScriptString)
640 QObject *target = stack.top();
641 QObject *scope = stack.at(stack.count() - 1 - instr.scope);
642 QDeclarativeScriptString ss;
643 ss.setContext(ctxt->asQDeclarativeContext());
644 ss.setScopeObject(scope);
645 ss.setScript(primitives.at(instr.value));
646 ss.d.data()->bindingId = instr.bindingId;
647 ss.d.data()->lineNumber = instr.line;
649 void *a[] = { &ss, 0, &status, &flags };
650 QMetaObject::metacall(target, QMetaObject::WriteProperty,
651 instr.propertyIndex, a);
652 QML_END_INSTR(StoreScriptString)
654 QML_BEGIN_INSTR(BeginObject)
655 QObject *target = stack.top();
656 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
657 parserStatus.append(status);
658 status->d = &parserStatus.values[parserStatus.count - 1];
660 status->classBegin();
661 QML_END_INSTR(BeginObject)
663 QML_BEGIN_INSTR(InitV8Bindings)
664 ctxt->v8bindings = new QV8Bindings(primitives.at(instr.program), instr.programIndex,
665 instr.line, comp, ctxt);
666 QML_END_INSTR(InitV8Bindings)
668 QML_BEGIN_INSTR(StoreBinding)
670 stack.at(stack.count() - 1 - instr.owner);
672 stack.at(stack.count() - 1 - instr.context);
674 QDeclarativeProperty mp =
675 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
677 int coreIndex = mp.index();
679 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
682 QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
683 context, ctxt, comp->name, instr.line);
684 bindValues.append(bind);
685 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
688 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
689 QML_END_INSTR(StoreBinding)
691 QML_BEGIN_INSTR(StoreBindingOnAlias)
693 stack.at(stack.count() - 1 - instr.owner);
695 stack.at(stack.count() - 1 - instr.context);
697 QDeclarativeProperty mp =
698 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
700 int coreIndex = mp.index();
702 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
705 QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
706 context, ctxt, comp->name, instr.line);
707 bindValues.append(bind);
708 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
711 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
712 if (old) { old->destroy(); }
713 QML_END_INSTR(StoreBindingOnAlias)
715 QML_BEGIN_INSTR(StoreV4Binding)
717 stack.at(stack.count() - 1 - instr.owner);
719 stack.at(stack.count() - 1 - instr.context);
721 int property = instr.property;
722 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
725 QDeclarativeAbstractBinding *binding =
726 ctxt->v4bindings->configBinding(instr.value, target, scope, property);
727 bindValues.append(binding);
728 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
729 binding->addToObject(target, property);
730 QML_END_INSTR(StoreV4Binding)
732 QML_BEGIN_INSTR(StoreV8Binding)
734 stack.at(stack.count() - 1 - instr.owner);
736 stack.at(stack.count() - 1 - instr.context);
738 QDeclarativeProperty mp =
739 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
741 int coreIndex = mp.index();
743 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
746 QDeclarativeAbstractBinding *binding =
747 ctxt->v8bindings->configBinding(instr.value, target, scope, mp, instr.line);
748 bindValues.append(binding);
749 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
750 binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
751 QML_END_INSTR(StoreV8Binding)
753 QML_BEGIN_INSTR(StoreValueSource)
754 QObject *obj = stack.pop();
755 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
756 QObject *target = stack.at(stack.count() - 1 - instr.owner);
758 QDeclarativeProperty prop =
759 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
760 obj->setParent(target);
762 QML_END_INSTR(StoreValueSource)
764 QML_BEGIN_INSTR(StoreValueInterceptor)
765 QObject *obj = stack.pop();
766 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
767 QObject *target = stack.at(stack.count() - 1 - instr.owner);
768 QDeclarativeProperty prop =
769 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
770 obj->setParent(target);
772 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
773 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
774 QML_END_INSTR(StoreValueInterceptor)
776 QML_BEGIN_INSTR(StoreObjectQList)
777 QObject *assign = stack.pop();
779 const ListInstance &list = qliststack.top();
780 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
781 QML_END_INSTR(StoreObjectQList)
783 QML_BEGIN_INSTR(AssignObjectList)
784 // This is only used for assigning interfaces
785 QObject *assign = stack.pop();
786 const ListInstance &list = qliststack.top();
788 int type = list.type;
792 const char *iid = QDeclarativeMetaType::interfaceIId(type);
794 ptr = assign->qt_metacast(iid);
796 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line);
799 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
800 QML_END_INSTR(AssignObjectList)
802 QML_BEGIN_INSTR(StoreVariantObject)
803 QObject *assign = stack.pop();
804 QObject *target = stack.top();
805 CLEAN_PROPERTY(target, instr.propertyIndex);
807 QVariant v = QVariant::fromValue(assign);
808 void *a[] = { &v, 0, &status, &flags };
809 QMetaObject::metacall(target, QMetaObject::WriteProperty,
810 instr.propertyIndex, a);
811 QML_END_INSTR(StoreVariantObject)
813 QML_BEGIN_INSTR(StoreInterface)
814 QObject *assign = stack.pop();
815 QObject *target = stack.top();
816 CLEAN_PROPERTY(target, instr.propertyIndex);
818 int coreIdx = instr.propertyIndex;
819 QMetaProperty prop = target->metaObject()->property(coreIdx);
820 int t = prop.userType();
821 const char *iid = QDeclarativeMetaType::interfaceIId(t);
824 void *ptr = assign->qt_metacast(iid);
826 void *a[] = { &ptr, 0, &status, &flags };
827 QMetaObject::metacall(target,
828 QMetaObject::WriteProperty,
835 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line);
836 QML_END_INSTR(StoreInterface)
838 QML_BEGIN_INSTR(FetchAttached)
839 QObject *target = stack.top();
841 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
844 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line);
846 stack.push(qmlObject);
847 QML_END_INSTR(FetchAttached)
849 QML_BEGIN_INSTR(FetchQList)
850 QObject *target = stack.top();
852 qliststack.push(ListInstance(instr.type));
855 a[0] = (void *)&(qliststack.top().qListProperty);
856 QMetaObject::metacall(target, QMetaObject::ReadProperty,
858 QML_END_INSTR(FetchQList)
860 QML_BEGIN_INSTR(FetchObject)
861 QObject *target = stack.top();
864 // NOTE: This assumes a cast to QObject does not alter the
868 QMetaObject::metacall(target, QMetaObject::ReadProperty,
872 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);
875 QML_END_INSTR(FetchObject)
877 QML_BEGIN_INSTR(PopQList)
879 QML_END_INSTR(PopQList)
881 QML_BEGIN_INSTR(Defer)
882 if (instr.deferCount) {
883 QObject *target = stack.top();
884 QDeclarativeData *data =
885 QDeclarativeData::get(target, true);
887 data->deferredComponent = comp;
888 data->deferredIdx = instructionStream - comp->bytecode.constData();
889 instructionStream += instr.deferCount;
893 QML_BEGIN_INSTR(PopFetchedObject)
895 QML_END_INSTR(PopFetchedObject)
897 QML_BEGIN_INSTR(FetchValueType)
898 QObject *target = stack.top();
900 if (instr.bindingSkipList != 0) {
901 // Possibly need to clear bindings
902 QDeclarativeData *targetData = QDeclarativeData::get(target);
904 QDeclarativeAbstractBinding *binding =
905 QDeclarativePropertyPrivate::binding(target, instr.property, -1);
907 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
908 QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
910 } else if (binding) {
911 QDeclarativeValueTypeProxyBinding *proxy =
912 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
913 proxy->removeBindings(instr.bindingSkipList);
918 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
919 valueHandler->read(target, instr.property);
920 stack.push(valueHandler);
921 QML_END_INSTR(FetchValueType)
923 QML_BEGIN_INSTR(PopValueType)
924 QDeclarativeValueType *valueHandler =
925 static_cast<QDeclarativeValueType *>(stack.pop());
926 QObject *target = stack.top();
927 valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
928 QML_END_INSTR(PopValueType)
931 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type());
937 if (!stack.isEmpty()) {
938 delete stack.at(0); // ### What about failures in deferred creation?
943 QDeclarativeEnginePrivate::clear(bindValues);
944 QDeclarativeEnginePrivate::clear(parserStatus);
948 if (bindValues.count)
949 ep->bindValues << bindValues;
950 else if (bindValues.values)
953 if (parserStatus.count)
954 ep->parserStatus << parserStatus;
955 else if (parserStatus.values)
956 parserStatus.clear();
958 Q_ASSERT(stack.count() == 1);
962 bool QDeclarativeVME::isError() const
964 return !vmeErrors.isEmpty();
967 QList<QDeclarativeError> QDeclarativeVME::errors() const
973 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
974 const QBitField &bindings,
975 QList<QDeclarativeError> *errors) const
981 type->create(&rv, &memory, sizeof(QDeclarativeData));
982 QDeclarativeData *ddata = new (memory) QDeclarativeData;
983 ddata->ownMemory = false;
984 QObjectPrivate::get(rv)->declarativeData = ddata;
986 if (typePropertyCache && !ddata->propertyCache) {
987 ddata->propertyCache = typePropertyCache;
988 ddata->propertyCache->addref();
994 return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings);
998 v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1000 if (script->m_loaded)
1001 return qPersistentNew<v8::Object>(script->m_value);
1003 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1004 QV8Engine *v8engine = &ep->v8engine;
1006 bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
1008 QDeclarativeContextData *effectiveCtxt = parentCtxt;
1012 // Create the script context if required
1013 QDeclarativeContextData *ctxt = new QDeclarativeContextData;
1014 ctxt->isInternal = true;
1015 ctxt->isJSContext = true;
1017 ctxt->isPragmaLibraryContext = true;
1019 ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
1020 ctxt->url = script->url;
1022 // For backward compatibility, if there are no imports, we need to use the
1023 // imports from the parent context. See QTBUG-17518.
1024 if (!script->importCache->isEmpty()) {
1025 ctxt->imports = script->importCache;
1026 } else if (effectiveCtxt) {
1027 ctxt->imports = effectiveCtxt->imports;
1028 ctxt->importedScripts = effectiveCtxt->importedScripts;
1029 for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
1030 ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
1033 if (ctxt->imports) {
1034 ctxt->imports->addref();
1038 ctxt->setParent(effectiveCtxt, true);
1040 for (int ii = 0; ii < script->scripts.count(); ++ii) {
1041 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1044 v8::HandleScope handle_scope;
1045 v8::Context::Scope scope(v8engine->context());
1047 v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
1049 v8::TryCatch try_catch;
1050 script->m_program->Run(qmlglobal);
1052 v8::Persistent<v8::Object> rv;
1054 if (try_catch.HasCaught()) {
1055 v8::Local<v8::Message> message = try_catch.Message();
1056 if (!message.IsEmpty()) {
1057 QDeclarativeError error;
1058 QDeclarativeExpressionPrivate::exceptionToError(message, error);
1063 rv = qPersistentNew<v8::Object>(qmlglobal);
1065 script->m_value = qPersistentNew<v8::Object>(qmlglobal);
1066 script->m_loaded = true;