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/qdeclarativeglobal_p.h"
62 #include "private/qdeclarativeglobalscriptclass_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 ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.compiledBinding).constData(), ctxt);
199 QML_BEGIN_INSTR(Done)
203 QML_BEGIN_INSTR(CreateObject)
205 if (instr.bindingBits != -1) {
206 const QByteArray &bits = datas.at(instr.bindingBits);
207 bindings = QBitField((const quint32*)bits.constData(),
211 bindings = bindings.united(bindingSkipList);
214 types.at(instr.type).createInstance(ctxt, bindings, &vmeErrors);
217 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.type).className)), instr.line);
220 QDeclarativeData *ddata = QDeclarativeData::get(o);
223 if (stack.isEmpty()) {
224 if (ddata->context) {
225 Q_ASSERT(ddata->context != ctxt);
226 Q_ASSERT(ddata->outerContext);
227 Q_ASSERT(ddata->outerContext != ctxt);
228 QDeclarativeContextData *c = ddata->context;
229 while (c->linkedContext) c = c->linkedContext;
230 c->linkedContext = ctxt;
235 ddata->ownContext = true;
236 } else if (!ddata->context) {
240 ddata->setImplicitDestructible();
241 ddata->outerContext = ctxt;
242 ddata->lineNumber = instr.line;
243 ddata->columnNumber = instr.column;
245 if (instr.data != -1) {
246 QDeclarativeCustomParser *customParser =
247 types.at(instr.type).type->customParser();
248 customParser->setCustomData(o, datas.at(instr.data));
250 if (!stack.isEmpty()) {
251 QObject *parent = stack.top();
252 if (o->isWidgetType()) {
253 QWidget *widget = static_cast<QWidget*>(o);
254 if (parent->isWidgetType()) {
255 QWidget *parentWidget = static_cast<QWidget*>(parent);
256 widget->setParent(parentWidget);
258 // TODO: parent might be a layout
261 QDeclarative_setParent_noEvent(o, parent);
265 QML_END_INSTR(CreateObject)
267 QML_BEGIN_INSTR(CreateSimpleObject)
268 QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));
269 ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
272 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
273 const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.type);
274 if (!ddata->propertyCache && ref.typePropertyCache) {
275 ddata->propertyCache = ref.typePropertyCache;
276 ddata->propertyCache->addref();
278 ddata->lineNumber = instr.line;
279 ddata->columnNumber = instr.column;
281 QObjectPrivate::get(o)->declarativeData = ddata;
282 ddata->context = ddata->outerContext = ctxt;
283 ddata->nextContextObject = ctxt->contextObjects;
284 if (ddata->nextContextObject)
285 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
286 ddata->prevContextObject = &ctxt->contextObjects;
287 ctxt->contextObjects = ddata;
289 QObject *parent = stack.top();
290 QDeclarative_setParent_noEvent(o, parent);
293 QML_END_INSTR(CreateSimpleObject)
295 QML_BEGIN_INSTR(SetId)
296 QObject *target = stack.top();
297 ctxt->setIdProperty(instr.index, target);
300 QML_BEGIN_INSTR(SetDefault)
301 ctxt->contextObject = stack.top();
302 QML_END_INSTR(SetDefault)
304 QML_BEGIN_INSTR(CreateComponent)
305 QDeclarativeComponent *qcomp =
306 new QDeclarativeComponent(ctxt->engine, comp, instructionStream - comp->bytecode.constData(),
307 stack.isEmpty() ? 0 : stack.top());
309 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
312 ctxt->addObject(qcomp);
315 ddata->ownContext = true;
317 ddata->setImplicitDestructible();
318 ddata->outerContext = ctxt;
319 ddata->lineNumber = instr.line;
320 ddata->columnNumber = instr.column;
322 QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
325 instructionStream += instr.count;
326 QML_END_INSTR(CreateComponent)
328 QML_BEGIN_INSTR(StoreMetaObject)
329 QObject *target = stack.top();
332 const QByteArray &metadata = datas.at(instr.data);
333 QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
335 const QDeclarativeVMEMetaData *data =
336 (const QDeclarativeVMEMetaData *)datas.at(instr.aliasData).constData();
338 (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
340 if (instr.propertyCache != -1) {
341 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
342 if (ddata->propertyCache) ddata->propertyCache->release();
343 ddata->propertyCache = propertyCaches.at(instr.propertyCache);
344 ddata->propertyCache->addref();
346 QML_END_INSTR(StoreMetaObject)
348 QML_BEGIN_INSTR(StoreVariant)
349 QObject *target = stack.top();
350 CLEAN_PROPERTY(target, instr.propertyIndex);
352 // XXX - can be more efficient
353 QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.value));
354 void *a[] = { &v, 0, &status, &flags };
355 QMetaObject::metacall(target, QMetaObject::WriteProperty,
356 instr.propertyIndex, a);
357 QML_END_INSTR(StoreVariant)
359 QML_BEGIN_INSTR(StoreVariantInteger)
360 QObject *target = stack.top();
361 CLEAN_PROPERTY(target, instr.propertyIndex);
363 QVariant v(instr.value);
364 void *a[] = { &v, 0, &status, &flags };
365 QMetaObject::metacall(target, QMetaObject::WriteProperty,
366 instr.propertyIndex, a);
367 QML_END_INSTR(StoreVariantInteger)
369 QML_BEGIN_INSTR(StoreVariantDouble)
370 QObject *target = stack.top();
371 CLEAN_PROPERTY(target, instr.propertyIndex);
373 QVariant v(instr.value);
374 void *a[] = { &v, 0, &status, &flags };
375 QMetaObject::metacall(target, QMetaObject::WriteProperty,
376 instr.propertyIndex, a);
377 QML_END_INSTR(StoreVariantDouble)
379 QML_BEGIN_INSTR(StoreVariantBool)
380 QObject *target = stack.top();
381 CLEAN_PROPERTY(target, instr.propertyIndex);
383 QVariant v(instr.value);
384 void *a[] = { &v, 0, &status, &flags };
385 QMetaObject::metacall(target, QMetaObject::WriteProperty,
386 instr.propertyIndex, a);
387 QML_END_INSTR(StoreVariantBool)
389 QML_BEGIN_INSTR(StoreString)
390 QObject *target = stack.top();
391 CLEAN_PROPERTY(target, instr.propertyIndex);
393 void *a[] = { (void *)&primitives.at(instr.value), 0, &status, &flags };
394 QMetaObject::metacall(target, QMetaObject::WriteProperty,
395 instr.propertyIndex, a);
396 QML_END_INSTR(StoreString)
398 QML_BEGIN_INSTR(StoreByteArray)
399 QObject *target = stack.top();
400 void *a[] = { (void *)&datas.at(instr.value), 0, &status, &flags };
401 QMetaObject::metacall(target, QMetaObject::WriteProperty,
402 instr.propertyIndex, a);
403 QML_END_INSTR(StoreByteArray)
405 QML_BEGIN_INSTR(StoreUrl)
406 QObject *target = stack.top();
407 CLEAN_PROPERTY(target, instr.propertyIndex);
409 void *a[] = { (void *)&urls.at(instr.value), 0, &status, &flags };
410 QMetaObject::metacall(target, QMetaObject::WriteProperty,
411 instr.propertyIndex, a);
412 QML_END_INSTR(StoreUrl)
414 QML_BEGIN_INSTR(StoreFloat)
415 QObject *target = stack.top();
416 CLEAN_PROPERTY(target, instr.propertyIndex);
418 float f = instr.value;
419 void *a[] = { &f, 0, &status, &flags };
420 QMetaObject::metacall(target, QMetaObject::WriteProperty,
421 instr.propertyIndex, a);
422 QML_END_INSTR(StoreFloat)
424 QML_BEGIN_INSTR(StoreDouble)
425 QObject *target = stack.top();
426 CLEAN_PROPERTY(target, instr.propertyIndex);
428 double d = instr.value;
429 void *a[] = { &d, 0, &status, &flags };
430 QMetaObject::metacall(target, QMetaObject::WriteProperty,
431 instr.propertyIndex, a);
432 QML_END_INSTR(StoreDouble)
434 QML_BEGIN_INSTR(StoreBool)
435 QObject *target = stack.top();
436 CLEAN_PROPERTY(target, instr.propertyIndex);
438 void *a[] = { (void *)&instr.value, 0, &status, &flags };
439 QMetaObject::metacall(target, QMetaObject::WriteProperty,
440 instr.propertyIndex, a);
441 QML_END_INSTR(StoreBool)
443 QML_BEGIN_INSTR(StoreInteger)
444 QObject *target = stack.top();
445 CLEAN_PROPERTY(target, instr.propertyIndex);
447 void *a[] = { (void *)&instr.value, 0, &status, &flags };
448 QMetaObject::metacall(target, QMetaObject::WriteProperty,
449 instr.propertyIndex, a);
450 QML_END_INSTR(StoreInteger)
452 QML_BEGIN_INSTR(StoreColor)
453 QObject *target = stack.top();
454 CLEAN_PROPERTY(target, instr.propertyIndex);
456 QColor c = QColor::fromRgba(instr.value);
457 void *a[] = { &c, 0, &status, &flags };
458 QMetaObject::metacall(target, QMetaObject::WriteProperty,
459 instr.propertyIndex, a);
460 QML_END_INSTR(StoreColor)
462 QML_BEGIN_INSTR(StoreDate)
463 QObject *target = stack.top();
464 CLEAN_PROPERTY(target, instr.propertyIndex);
466 QDate d = QDate::fromJulianDay(instr.value);
467 void *a[] = { &d, 0, &status, &flags };
468 QMetaObject::metacall(target, QMetaObject::WriteProperty,
469 instr.propertyIndex, a);
470 QML_END_INSTR(StoreDate)
472 QML_BEGIN_INSTR(StoreTime)
473 QObject *target = stack.top();
474 CLEAN_PROPERTY(target, instr.propertyIndex);
476 QTime *t = (QTime *)&instr.time;
477 void *a[] = { t, 0, &status, &flags };
478 QMetaObject::metacall(target, QMetaObject::WriteProperty,
479 instr.propertyIndex, a);
480 QML_END_INSTR(StoreTime)
482 QML_BEGIN_INSTR(StoreDateTime)
483 QObject *target = stack.top();
484 CLEAN_PROPERTY(target, instr.propertyIndex);
486 QTime *t = (QTime *)&instr.time;
487 QDateTime dt(QDate::fromJulianDay(instr.date), *t);
488 void *a[] = { &dt, 0, &status, &flags };
489 QMetaObject::metacall(target, QMetaObject::WriteProperty,
490 instr.propertyIndex, a);
491 QML_END_INSTR(StoreDateTime)
493 QML_BEGIN_INSTR(StorePoint)
494 QObject *target = stack.top();
495 CLEAN_PROPERTY(target, instr.propertyIndex);
497 QPoint *p = (QPoint *)&instr.point;
498 void *a[] = { p, 0, &status, &flags };
499 QMetaObject::metacall(target, QMetaObject::WriteProperty,
500 instr.propertyIndex, a);
501 QML_END_INSTR(StorePoint)
503 QML_BEGIN_INSTR(StorePointF)
504 QObject *target = stack.top();
505 CLEAN_PROPERTY(target, instr.propertyIndex);
507 QPointF *p = (QPointF *)&instr.point;
508 void *a[] = { p, 0, &status, &flags };
509 QMetaObject::metacall(target, QMetaObject::WriteProperty,
510 instr.propertyIndex, a);
511 QML_END_INSTR(StorePointF)
513 QML_BEGIN_INSTR(StoreSize)
514 QObject *target = stack.top();
515 CLEAN_PROPERTY(target, instr.propertyIndex);
517 QSize *s = (QSize *)&instr.size;
518 void *a[] = { s, 0, &status, &flags };
519 QMetaObject::metacall(target, QMetaObject::WriteProperty,
520 instr.propertyIndex, a);
521 QML_END_INSTR(StoreSize)
523 QML_BEGIN_INSTR(StoreSizeF)
524 QObject *target = stack.top();
525 CLEAN_PROPERTY(target, instr.propertyIndex);
527 QSizeF *s = (QSizeF *)&instr.size;
528 void *a[] = { s, 0, &status, &flags };
529 QMetaObject::metacall(target, QMetaObject::WriteProperty,
530 instr.propertyIndex, a);
531 QML_END_INSTR(StoreSizeF)
533 QML_BEGIN_INSTR(StoreRect)
534 QObject *target = stack.top();
535 CLEAN_PROPERTY(target, instr.propertyIndex);
537 QRect *r = (QRect *)&instr.rect;
538 void *a[] = { r, 0, &status, &flags };
539 QMetaObject::metacall(target, QMetaObject::WriteProperty,
540 instr.propertyIndex, a);
541 QML_END_INSTR(StoreRect)
543 QML_BEGIN_INSTR(StoreRectF)
544 QObject *target = stack.top();
545 CLEAN_PROPERTY(target, instr.propertyIndex);
547 QRectF *r = (QRectF *)&instr.rect;
548 void *a[] = { r, 0, &status, &flags };
549 QMetaObject::metacall(target, QMetaObject::WriteProperty,
550 instr.propertyIndex, a);
551 QML_END_INSTR(StoreRectF)
553 QML_BEGIN_INSTR(StoreVector3D)
554 QObject *target = stack.top();
555 CLEAN_PROPERTY(target, instr.propertyIndex);
557 QVector3D *v = (QVector3D *)&instr.vector;
558 void *a[] = { v, 0, &status, &flags };
559 QMetaObject::metacall(target, QMetaObject::WriteProperty,
560 instr.propertyIndex, a);
561 QML_END_INSTR(StoreVector3D)
563 QML_BEGIN_INSTR(StoreObject)
564 QObject *assignObj = stack.pop();
565 QObject *target = stack.top();
566 CLEAN_PROPERTY(target, instr.propertyIndex);
568 void *a[] = { (void *)&assignObj, 0, &status, &flags };
569 QMetaObject::metacall(target, QMetaObject::WriteProperty,
570 instr.propertyIndex, a);
571 QML_END_INSTR(StoreObject)
573 QML_BEGIN_INSTR(AssignCustomType)
574 QObject *target = stack.top();
575 CLEAN_PROPERTY(target, instr.propertyIndex);
577 const QString &primitive = primitives.at(instr.primitive);
578 int type = instr.type;
579 QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
580 QVariant v = (*converter)(primitive);
583 target->metaObject()->property(instr.propertyIndex);
584 if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
585 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
587 void *a[] = { (void *)v.data(), 0, &status, &flags };
588 QMetaObject::metacall(target, QMetaObject::WriteProperty,
589 instr.propertyIndex, a);
590 QML_END_INSTR(AssignCustomType)
592 QML_BEGIN_INSTR(AssignSignalObject)
595 QObject *assign = stack.pop();
596 QObject *target = stack.top();
597 int sigIdx = instr.signal;
598 const QByteArray &pr = datas.at(sigIdx);
600 QDeclarativeProperty prop(target, QString::fromUtf8(pr));
601 if (prop.type() & QDeclarativeProperty::SignalProperty) {
603 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
604 if (method.signature() == 0)
605 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
607 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
608 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);
610 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
613 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.line);
617 QML_END_INSTR(AssignSignalObject)
619 QML_BEGIN_INSTR(StoreSignal)
620 QObject *target = stack.top();
621 QObject *context = stack.at(stack.count() - 1 - instr.context);
623 QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
625 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
626 QDeclarativeExpression *expr =
627 new QDeclarativeExpression(ctxt, context, primitives.at(instr.value));
628 expr->setSourceLocation(comp->name, instr.line);
629 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.name);
630 bs->setExpression(expr);
631 QML_END_INSTR(StoreSignal)
633 QML_BEGIN_INSTR(StoreImportedScript)
634 ctxt->importedScripts << run(ctxt, scripts.at(instr.value));
635 QML_END_INSTR(StoreImportedScript)
637 QML_BEGIN_INSTR(StoreScriptString)
638 QObject *target = stack.top();
639 QObject *scope = stack.at(stack.count() - 1 - instr.scope);
640 QDeclarativeScriptString ss;
641 ss.setContext(ctxt->asQDeclarativeContext());
642 ss.setScopeObject(scope);
643 ss.setScript(primitives.at(instr.value));
644 ss.d.data()->bindingId = instr.bindingId;
645 ss.d.data()->lineNumber = instr.line;
647 void *a[] = { &ss, 0, &status, &flags };
648 QMetaObject::metacall(target, QMetaObject::WriteProperty,
649 instr.propertyIndex, a);
650 QML_END_INSTR(StoreScriptString)
652 QML_BEGIN_INSTR(BeginObject)
653 QObject *target = stack.top();
654 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
655 parserStatus.append(status);
656 status->d = &parserStatus.values[parserStatus.count - 1];
658 status->classBegin();
659 QML_END_INSTR(BeginObject)
661 QML_BEGIN_INSTR(StoreBinding)
663 stack.at(stack.count() - 1 - instr.owner);
665 stack.at(stack.count() - 1 - instr.context);
667 QDeclarativeProperty mp =
668 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
670 int coreIndex = mp.index();
672 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
675 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
676 bindValues.append(bind);
677 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
680 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
681 QML_END_INSTR(StoreBinding)
683 QML_BEGIN_INSTR(StoreBindingOnAlias)
685 stack.at(stack.count() - 1 - instr.owner);
687 stack.at(stack.count() - 1 - instr.context);
689 QDeclarativeProperty mp =
690 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
692 int coreIndex = mp.index();
694 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
697 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
698 bindValues.append(bind);
699 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
702 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
703 if (old) { old->destroy(); }
704 QML_END_INSTR(StoreBindingOnAlias)
706 QML_BEGIN_INSTR(StoreCompiledBinding)
708 stack.at(stack.count() - 1 - instr.owner);
710 stack.at(stack.count() - 1 - instr.context);
712 int property = instr.property;
713 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
716 QDeclarativeAbstractBinding *binding =
717 ctxt->optimizedBindings->configBinding(instr.value, target, scope, property);
718 bindValues.append(binding);
719 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
720 binding->addToObject(target, property);
721 QML_END_INSTR(StoreCompiledBinding)
723 QML_BEGIN_INSTR(StoreValueSource)
724 QObject *obj = stack.pop();
725 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
726 QObject *target = stack.at(stack.count() - 1 - instr.owner);
728 QDeclarativeProperty prop =
729 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
730 obj->setParent(target);
732 QML_END_INSTR(StoreValueSource)
734 QML_BEGIN_INSTR(StoreValueInterceptor)
735 QObject *obj = stack.pop();
736 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
737 QObject *target = stack.at(stack.count() - 1 - instr.owner);
738 QDeclarativeProperty prop =
739 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
740 obj->setParent(target);
742 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
743 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
744 QML_END_INSTR(StoreValueInterceptor)
746 QML_BEGIN_INSTR(StoreObjectQList)
747 QObject *assign = stack.pop();
749 const ListInstance &list = qliststack.top();
750 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
751 QML_END_INSTR(StoreObjectQList)
753 QML_BEGIN_INSTR(AssignObjectList)
754 // This is only used for assigning interfaces
755 QObject *assign = stack.pop();
756 const ListInstance &list = qliststack.top();
758 int type = list.type;
762 const char *iid = QDeclarativeMetaType::interfaceIId(type);
764 ptr = assign->qt_metacast(iid);
766 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line);
769 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
770 QML_END_INSTR(AssignObjectList)
772 QML_BEGIN_INSTR(StoreVariantObject)
773 QObject *assign = stack.pop();
774 QObject *target = stack.top();
775 CLEAN_PROPERTY(target, instr.propertyIndex);
777 QVariant v = QVariant::fromValue(assign);
778 void *a[] = { &v, 0, &status, &flags };
779 QMetaObject::metacall(target, QMetaObject::WriteProperty,
780 instr.propertyIndex, a);
781 QML_END_INSTR(StoreVariantObject)
783 QML_BEGIN_INSTR(StoreInterface)
784 QObject *assign = stack.pop();
785 QObject *target = stack.top();
786 CLEAN_PROPERTY(target, instr.propertyIndex);
788 int coreIdx = instr.propertyIndex;
789 QMetaProperty prop = target->metaObject()->property(coreIdx);
790 int t = prop.userType();
791 const char *iid = QDeclarativeMetaType::interfaceIId(t);
794 void *ptr = assign->qt_metacast(iid);
796 void *a[] = { &ptr, 0, &status, &flags };
797 QMetaObject::metacall(target,
798 QMetaObject::WriteProperty,
805 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line);
806 QML_END_INSTR(StoreInterface)
808 QML_BEGIN_INSTR(FetchAttached)
809 QObject *target = stack.top();
811 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
814 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line);
816 stack.push(qmlObject);
817 QML_END_INSTR(FetchAttached)
819 QML_BEGIN_INSTR(FetchQList)
820 QObject *target = stack.top();
822 qliststack.push(ListInstance(instr.type));
825 a[0] = (void *)&(qliststack.top().qListProperty);
826 QMetaObject::metacall(target, QMetaObject::ReadProperty,
828 QML_END_INSTR(FetchQList)
830 QML_BEGIN_INSTR(FetchObject)
831 QObject *target = stack.top();
834 // NOTE: This assumes a cast to QObject does not alter the
838 QMetaObject::metacall(target, QMetaObject::ReadProperty,
842 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);
845 QML_END_INSTR(FetchObject)
847 QML_BEGIN_INSTR(PopQList)
849 QML_END_INSTR(PopQList)
851 QML_BEGIN_INSTR(Defer)
852 if (instr.deferCount) {
853 QObject *target = stack.top();
854 QDeclarativeData *data =
855 QDeclarativeData::get(target, true);
857 data->deferredComponent = comp;
858 data->deferredIdx = instructionStream - comp->bytecode.constData();
859 instructionStream += instr.deferCount;
863 QML_BEGIN_INSTR(PopFetchedObject)
865 QML_END_INSTR(PopFetchedObject)
867 QML_BEGIN_INSTR(FetchValueType)
868 QObject *target = stack.top();
870 if (instr.bindingSkipList != 0) {
871 // Possibly need to clear bindings
872 QDeclarativeData *targetData = QDeclarativeData::get(target);
874 QDeclarativeAbstractBinding *binding =
875 QDeclarativePropertyPrivate::binding(target, instr.property, -1);
877 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
878 QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
880 } else if (binding) {
881 QDeclarativeValueTypeProxyBinding *proxy =
882 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
883 proxy->removeBindings(instr.bindingSkipList);
888 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
889 valueHandler->read(target, instr.property);
890 stack.push(valueHandler);
891 QML_END_INSTR(FetchValueType)
893 QML_BEGIN_INSTR(PopValueType)
894 QDeclarativeValueType *valueHandler =
895 static_cast<QDeclarativeValueType *>(stack.pop());
896 QObject *target = stack.top();
897 valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
898 QML_END_INSTR(PopValueType)
901 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type());
907 if (!stack.isEmpty()) {
908 delete stack.at(0); // ### What about failures in deferred creation?
913 QDeclarativeEnginePrivate::clear(bindValues);
914 QDeclarativeEnginePrivate::clear(parserStatus);
918 if (bindValues.count)
919 ep->bindValues << bindValues;
920 else if (bindValues.values)
923 if (parserStatus.count)
924 ep->parserStatus << parserStatus;
925 else if (parserStatus.values)
926 parserStatus.clear();
928 Q_ASSERT(stack.count() == 1);
932 bool QDeclarativeVME::isError() const
934 return !vmeErrors.isEmpty();
937 QList<QDeclarativeError> QDeclarativeVME::errors() const
943 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
944 const QBitField &bindings,
945 QList<QDeclarativeError> *errors) const
951 type->create(&rv, &memory, sizeof(QDeclarativeData));
952 QDeclarativeData *ddata = new (memory) QDeclarativeData;
953 ddata->ownMemory = false;
954 QObjectPrivate::get(rv)->declarativeData = ddata;
956 if (typePropertyCache && !ddata->propertyCache) {
957 ddata->propertyCache = typePropertyCache;
958 ddata->propertyCache->addref();
964 return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings);
968 QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
970 if (script->m_loaded)
971 return script->m_value;
973 QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine);
974 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine);
976 bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
978 // Create the script context if required
979 QDeclarativeContextData *ctxt = 0;
981 ctxt = new QDeclarativeContextData;
982 ctxt->isInternal = true;
983 ctxt->url = script->url;
985 // For backward compatibility, if there are no imports, we need to use the
986 // imports from the parent context. See QTBUG-17518.
987 if (!script->importCache->isEmpty()) {
988 ctxt->imports = script->importCache;
990 ctxt->imports = parentCtxt->imports;
994 ctxt->imports->addref();
997 ctxt->setParent(parentCtxt, true);
999 for (int ii = 0; ii < script->scripts.count(); ++ii)
1000 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1003 QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
1005 scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()?
1007 scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString()));
1010 scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
1011 QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
1012 scriptContext->pushScope(scope);
1014 scriptEngine->evaluate(script->m_program);
1016 if (scriptEngine->hasUncaughtException()) {
1017 QDeclarativeError error;
1018 QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
1019 enginePriv->warning(error);
1022 scriptEngine->popContext();
1025 script->m_loaded = true;
1026 script->m_value = scope;