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"
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<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches;
165 const QList<QDeclarativeScriptData *> &scripts = comp->scripts;
166 const QList<QUrl> &urls = comp->urls;
168 QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues;
169 QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus;
171 QDeclarativeVMEStack<ListInstance> qliststack;
174 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
176 int status = -1; //for dbus
177 QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
178 QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
180 const char *instructionStream = comp->bytecode.constData() + start;
183 while (!isError() && !done) {
184 const QDeclarativeInstruction &genericInstr = *((QDeclarativeInstruction *)instructionStream);
186 switch(genericInstr.type()) {
187 QML_BEGIN_INSTR(Init)
188 if (instr.bindingsSize)
189 bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.bindingsSize);
190 if (instr.parserStatusSize)
191 parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.parserStatusSize);
192 if (instr.contextCache != -1)
193 ctxt->setIdPropertyData(comp->contextCaches.at(instr.contextCache));
194 if (instr.compiledBinding != -1)
195 ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.compiledBinding).constData(), ctxt);
198 QML_BEGIN_INSTR(Done)
202 QML_BEGIN_INSTR(CreateObject)
204 if (instr.bindingBits != -1) {
205 const QByteArray &bits = datas.at(instr.bindingBits);
206 bindings = QBitField((const quint32*)bits.constData(),
210 bindings = bindings.united(bindingSkipList);
213 types.at(instr.type).createInstance(ctxt, bindings, &vmeErrors);
216 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.type).className)), instr.line);
219 QDeclarativeData *ddata = QDeclarativeData::get(o);
222 if (stack.isEmpty()) {
223 if (ddata->context) {
224 Q_ASSERT(ddata->context != ctxt);
225 Q_ASSERT(ddata->outerContext);
226 Q_ASSERT(ddata->outerContext != ctxt);
227 QDeclarativeContextData *c = ddata->context;
228 while (c->linkedContext) c = c->linkedContext;
229 c->linkedContext = ctxt;
234 ddata->ownContext = true;
235 } else if (!ddata->context) {
239 ddata->setImplicitDestructible();
240 ddata->outerContext = ctxt;
241 ddata->lineNumber = instr.line;
242 ddata->columnNumber = instr.column;
244 if (instr.data != -1) {
245 QDeclarativeCustomParser *customParser =
246 types.at(instr.type).type->customParser();
247 customParser->setCustomData(o, datas.at(instr.data));
249 if (!stack.isEmpty()) {
250 QObject *parent = stack.top();
251 if (o->isWidgetType()) {
252 QWidget *widget = static_cast<QWidget*>(o);
253 if (parent->isWidgetType()) {
254 QWidget *parentWidget = static_cast<QWidget*>(parent);
255 widget->setParent(parentWidget);
257 // TODO: parent might be a layout
260 QDeclarative_setParent_noEvent(o, parent);
264 QML_END_INSTR(CreateObject)
266 QML_BEGIN_INSTR(CreateSimpleObject)
267 QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));
268 ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
271 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
272 const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.type);
273 if (!ddata->propertyCache && ref.typePropertyCache) {
274 ddata->propertyCache = ref.typePropertyCache;
275 ddata->propertyCache->addref();
277 ddata->lineNumber = instr.line;
278 ddata->columnNumber = instr.column;
280 QObjectPrivate::get(o)->declarativeData = ddata;
281 ddata->context = ddata->outerContext = ctxt;
282 ddata->nextContextObject = ctxt->contextObjects;
283 if (ddata->nextContextObject)
284 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
285 ddata->prevContextObject = &ctxt->contextObjects;
286 ctxt->contextObjects = ddata;
288 QObject *parent = stack.top();
289 QDeclarative_setParent_noEvent(o, parent);
292 QML_END_INSTR(CreateSimpleObject)
294 QML_BEGIN_INSTR(SetId)
295 QObject *target = stack.top();
296 ctxt->setIdProperty(instr.index, target);
299 QML_BEGIN_INSTR(SetDefault)
300 ctxt->contextObject = stack.top();
301 QML_END_INSTR(SetDefault)
303 QML_BEGIN_INSTR(CreateComponent)
304 QDeclarativeComponent *qcomp =
305 new QDeclarativeComponent(ctxt->engine, comp, instructionStream - comp->bytecode.constData(),
306 stack.isEmpty() ? 0 : stack.top());
308 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
311 ctxt->addObject(qcomp);
314 ddata->ownContext = true;
316 ddata->setImplicitDestructible();
317 ddata->outerContext = ctxt;
318 ddata->lineNumber = instr.line;
319 ddata->columnNumber = instr.column;
321 QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
324 instructionStream += instr.count;
325 QML_END_INSTR(CreateComponent)
327 QML_BEGIN_INSTR(StoreMetaObject)
328 QObject *target = stack.top();
331 const QByteArray &metadata = datas.at(instr.data);
332 QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
334 const QDeclarativeVMEMetaData *data =
335 (const QDeclarativeVMEMetaData *)datas.at(instr.aliasData).constData();
337 (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
339 if (instr.propertyCache != -1) {
340 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
341 if (ddata->propertyCache) ddata->propertyCache->release();
342 ddata->propertyCache = propertyCaches.at(instr.propertyCache);
343 ddata->propertyCache->addref();
345 QML_END_INSTR(StoreMetaObject)
347 QML_BEGIN_INSTR(StoreVariant)
348 QObject *target = stack.top();
349 CLEAN_PROPERTY(target, instr.propertyIndex);
351 // XXX - can be more efficient
352 QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.value));
353 void *a[] = { &v, 0, &status, &flags };
354 QMetaObject::metacall(target, QMetaObject::WriteProperty,
355 instr.propertyIndex, a);
356 QML_END_INSTR(StoreVariant)
358 QML_BEGIN_INSTR(StoreVariantInteger)
359 QObject *target = stack.top();
360 CLEAN_PROPERTY(target, instr.propertyIndex);
362 QVariant v(instr.value);
363 void *a[] = { &v, 0, &status, &flags };
364 QMetaObject::metacall(target, QMetaObject::WriteProperty,
365 instr.propertyIndex, a);
366 QML_END_INSTR(StoreVariantInteger)
368 QML_BEGIN_INSTR(StoreVariantDouble)
369 QObject *target = stack.top();
370 CLEAN_PROPERTY(target, instr.propertyIndex);
372 QVariant v(instr.value);
373 void *a[] = { &v, 0, &status, &flags };
374 QMetaObject::metacall(target, QMetaObject::WriteProperty,
375 instr.propertyIndex, a);
376 QML_END_INSTR(StoreVariantDouble)
378 QML_BEGIN_INSTR(StoreVariantBool)
379 QObject *target = stack.top();
380 CLEAN_PROPERTY(target, instr.propertyIndex);
382 QVariant v(instr.value);
383 void *a[] = { &v, 0, &status, &flags };
384 QMetaObject::metacall(target, QMetaObject::WriteProperty,
385 instr.propertyIndex, a);
386 QML_END_INSTR(StoreVariantBool)
388 QML_BEGIN_INSTR(StoreString)
389 QObject *target = stack.top();
390 CLEAN_PROPERTY(target, instr.propertyIndex);
392 void *a[] = { (void *)&primitives.at(instr.value), 0, &status, &flags };
393 QMetaObject::metacall(target, QMetaObject::WriteProperty,
394 instr.propertyIndex, a);
395 QML_END_INSTR(StoreString)
397 QML_BEGIN_INSTR(StoreByteArray)
398 QObject *target = stack.top();
399 void *a[] = { (void *)&datas.at(instr.value), 0, &status, &flags };
400 QMetaObject::metacall(target, QMetaObject::WriteProperty,
401 instr.propertyIndex, a);
402 QML_END_INSTR(StoreByteArray)
404 QML_BEGIN_INSTR(StoreUrl)
405 QObject *target = stack.top();
406 CLEAN_PROPERTY(target, instr.propertyIndex);
408 void *a[] = { (void *)&urls.at(instr.value), 0, &status, &flags };
409 QMetaObject::metacall(target, QMetaObject::WriteProperty,
410 instr.propertyIndex, a);
411 QML_END_INSTR(StoreUrl)
413 QML_BEGIN_INSTR(StoreFloat)
414 QObject *target = stack.top();
415 CLEAN_PROPERTY(target, instr.propertyIndex);
417 float f = instr.value;
418 void *a[] = { &f, 0, &status, &flags };
419 QMetaObject::metacall(target, QMetaObject::WriteProperty,
420 instr.propertyIndex, a);
421 QML_END_INSTR(StoreFloat)
423 QML_BEGIN_INSTR(StoreDouble)
424 QObject *target = stack.top();
425 CLEAN_PROPERTY(target, instr.propertyIndex);
427 double d = instr.value;
428 void *a[] = { &d, 0, &status, &flags };
429 QMetaObject::metacall(target, QMetaObject::WriteProperty,
430 instr.propertyIndex, a);
431 QML_END_INSTR(StoreDouble)
433 QML_BEGIN_INSTR(StoreBool)
434 QObject *target = stack.top();
435 CLEAN_PROPERTY(target, instr.propertyIndex);
437 void *a[] = { (void *)&instr.value, 0, &status, &flags };
438 QMetaObject::metacall(target, QMetaObject::WriteProperty,
439 instr.propertyIndex, a);
440 QML_END_INSTR(StoreBool)
442 QML_BEGIN_INSTR(StoreInteger)
443 QObject *target = stack.top();
444 CLEAN_PROPERTY(target, instr.propertyIndex);
446 void *a[] = { (void *)&instr.value, 0, &status, &flags };
447 QMetaObject::metacall(target, QMetaObject::WriteProperty,
448 instr.propertyIndex, a);
449 QML_END_INSTR(StoreInteger)
451 QML_BEGIN_INSTR(StoreColor)
452 QObject *target = stack.top();
453 CLEAN_PROPERTY(target, instr.propertyIndex);
455 QColor c = QColor::fromRgba(instr.value);
456 void *a[] = { &c, 0, &status, &flags };
457 QMetaObject::metacall(target, QMetaObject::WriteProperty,
458 instr.propertyIndex, a);
459 QML_END_INSTR(StoreColor)
461 QML_BEGIN_INSTR(StoreDate)
462 QObject *target = stack.top();
463 CLEAN_PROPERTY(target, instr.propertyIndex);
465 QDate d = QDate::fromJulianDay(instr.value);
466 void *a[] = { &d, 0, &status, &flags };
467 QMetaObject::metacall(target, QMetaObject::WriteProperty,
468 instr.propertyIndex, a);
469 QML_END_INSTR(StoreDate)
471 QML_BEGIN_INSTR(StoreTime)
472 QObject *target = stack.top();
473 CLEAN_PROPERTY(target, instr.propertyIndex);
475 QTime *t = (QTime *)&instr.time;
476 void *a[] = { t, 0, &status, &flags };
477 QMetaObject::metacall(target, QMetaObject::WriteProperty,
478 instr.propertyIndex, a);
479 QML_END_INSTR(StoreTime)
481 QML_BEGIN_INSTR(StoreDateTime)
482 QObject *target = stack.top();
483 CLEAN_PROPERTY(target, instr.propertyIndex);
485 QTime *t = (QTime *)&instr.time;
486 QDateTime dt(QDate::fromJulianDay(instr.date), *t);
487 void *a[] = { &dt, 0, &status, &flags };
488 QMetaObject::metacall(target, QMetaObject::WriteProperty,
489 instr.propertyIndex, a);
490 QML_END_INSTR(StoreDateTime)
492 QML_BEGIN_INSTR(StorePoint)
493 QObject *target = stack.top();
494 CLEAN_PROPERTY(target, instr.propertyIndex);
496 QPoint *p = (QPoint *)&instr.point;
497 void *a[] = { p, 0, &status, &flags };
498 QMetaObject::metacall(target, QMetaObject::WriteProperty,
499 instr.propertyIndex, a);
500 QML_END_INSTR(StorePoint)
502 QML_BEGIN_INSTR(StorePointF)
503 QObject *target = stack.top();
504 CLEAN_PROPERTY(target, instr.propertyIndex);
506 QPointF *p = (QPointF *)&instr.point;
507 void *a[] = { p, 0, &status, &flags };
508 QMetaObject::metacall(target, QMetaObject::WriteProperty,
509 instr.propertyIndex, a);
510 QML_END_INSTR(StorePointF)
512 QML_BEGIN_INSTR(StoreSize)
513 QObject *target = stack.top();
514 CLEAN_PROPERTY(target, instr.propertyIndex);
516 QSize *s = (QSize *)&instr.size;
517 void *a[] = { s, 0, &status, &flags };
518 QMetaObject::metacall(target, QMetaObject::WriteProperty,
519 instr.propertyIndex, a);
520 QML_END_INSTR(StoreSize)
522 QML_BEGIN_INSTR(StoreSizeF)
523 QObject *target = stack.top();
524 CLEAN_PROPERTY(target, instr.propertyIndex);
526 QSizeF *s = (QSizeF *)&instr.size;
527 void *a[] = { s, 0, &status, &flags };
528 QMetaObject::metacall(target, QMetaObject::WriteProperty,
529 instr.propertyIndex, a);
530 QML_END_INSTR(StoreSizeF)
532 QML_BEGIN_INSTR(StoreRect)
533 QObject *target = stack.top();
534 CLEAN_PROPERTY(target, instr.propertyIndex);
536 QRect *r = (QRect *)&instr.rect;
537 void *a[] = { r, 0, &status, &flags };
538 QMetaObject::metacall(target, QMetaObject::WriteProperty,
539 instr.propertyIndex, a);
540 QML_END_INSTR(StoreRect)
542 QML_BEGIN_INSTR(StoreRectF)
543 QObject *target = stack.top();
544 CLEAN_PROPERTY(target, instr.propertyIndex);
546 QRectF *r = (QRectF *)&instr.rect;
547 void *a[] = { r, 0, &status, &flags };
548 QMetaObject::metacall(target, QMetaObject::WriteProperty,
549 instr.propertyIndex, a);
550 QML_END_INSTR(StoreRectF)
552 QML_BEGIN_INSTR(StoreVector3D)
553 QObject *target = stack.top();
554 CLEAN_PROPERTY(target, instr.propertyIndex);
556 QVector3D *v = (QVector3D *)&instr.vector;
557 void *a[] = { v, 0, &status, &flags };
558 QMetaObject::metacall(target, QMetaObject::WriteProperty,
559 instr.propertyIndex, a);
560 QML_END_INSTR(StoreVector3D)
562 QML_BEGIN_INSTR(StoreObject)
563 QObject *assignObj = stack.pop();
564 QObject *target = stack.top();
565 CLEAN_PROPERTY(target, instr.propertyIndex);
567 void *a[] = { (void *)&assignObj, 0, &status, &flags };
568 QMetaObject::metacall(target, QMetaObject::WriteProperty,
569 instr.propertyIndex, a);
570 QML_END_INSTR(StoreObject)
572 QML_BEGIN_INSTR(AssignCustomType)
573 QObject *target = stack.top();
574 CLEAN_PROPERTY(target, instr.propertyIndex);
576 const QString &primitive = primitives.at(instr.primitive);
577 int type = instr.type;
578 QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
579 QVariant v = (*converter)(primitive);
582 target->metaObject()->property(instr.propertyIndex);
583 if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
584 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
586 void *a[] = { (void *)v.data(), 0, &status, &flags };
587 QMetaObject::metacall(target, QMetaObject::WriteProperty,
588 instr.propertyIndex, a);
589 QML_END_INSTR(AssignCustomType)
591 QML_BEGIN_INSTR(AssignSignalObject)
594 QObject *assign = stack.pop();
595 QObject *target = stack.top();
596 int sigIdx = instr.signal;
597 const QByteArray &pr = datas.at(sigIdx);
599 QDeclarativeProperty prop(target, QString::fromUtf8(pr));
600 if (prop.type() & QDeclarativeProperty::SignalProperty) {
602 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
603 if (method.signature() == 0)
604 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
606 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
607 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);
609 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
612 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.line);
616 QML_END_INSTR(AssignSignalObject)
618 QML_BEGIN_INSTR(StoreSignal)
619 QObject *target = stack.top();
620 QObject *context = stack.at(stack.count() - 1 - instr.context);
622 QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
624 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
625 QDeclarativeExpression *expr =
626 new QDeclarativeExpression(ctxt, context, primitives.at(instr.value));
627 expr->setSourceLocation(comp->name, instr.line);
628 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.name);
629 bs->setExpression(expr);
630 QML_END_INSTR(StoreSignal)
632 QML_BEGIN_INSTR(StoreImportedScript)
633 ctxt->importedScripts << run(ctxt, scripts.at(instr.value));
634 QML_END_INSTR(StoreImportedScript)
636 QML_BEGIN_INSTR(StoreScriptString)
637 QObject *target = stack.top();
638 QObject *scope = stack.at(stack.count() - 1 - instr.scope);
639 QDeclarativeScriptString ss;
640 ss.setContext(ctxt->asQDeclarativeContext());
641 ss.setScopeObject(scope);
642 ss.setScript(primitives.at(instr.value));
644 void *a[] = { &ss, 0, &status, &flags };
645 QMetaObject::metacall(target, QMetaObject::WriteProperty,
646 instr.propertyIndex, a);
647 QML_END_INSTR(StoreScriptString)
649 QML_BEGIN_INSTR(BeginObject)
650 QObject *target = stack.top();
651 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
652 parserStatus.append(status);
653 status->d = &parserStatus.values[parserStatus.count - 1];
655 status->classBegin();
656 QML_END_INSTR(BeginObject)
658 QML_BEGIN_INSTR(StoreBinding)
660 stack.at(stack.count() - 1 - instr.owner);
662 stack.at(stack.count() - 1 - instr.context);
664 QDeclarativeProperty mp =
665 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
667 int coreIndex = mp.index();
669 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
672 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
673 bindValues.append(bind);
674 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
677 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
678 QML_END_INSTR(StoreBinding)
680 QML_BEGIN_INSTR(StoreBindingOnAlias)
682 stack.at(stack.count() - 1 - instr.owner);
684 stack.at(stack.count() - 1 - instr.context);
686 QDeclarativeProperty mp =
687 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
689 int coreIndex = mp.index();
691 if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
694 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
695 bindValues.append(bind);
696 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
699 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
700 if (old) { old->destroy(); }
701 QML_END_INSTR(StoreBindingOnAlias)
703 QML_BEGIN_INSTR(StoreCompiledBinding)
705 stack.at(stack.count() - 1 - instr.owner);
707 stack.at(stack.count() - 1 - instr.context);
709 int property = instr.property;
710 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
713 QDeclarativeAbstractBinding *binding =
714 ctxt->optimizedBindings->configBinding(instr.value, target, scope, property);
715 bindValues.append(binding);
716 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
717 binding->addToObject(target, property);
718 QML_END_INSTR(StoreCompiledBinding)
720 QML_BEGIN_INSTR(StoreValueSource)
721 QObject *obj = stack.pop();
722 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
723 QObject *target = stack.at(stack.count() - 1 - instr.owner);
725 QDeclarativeProperty prop =
726 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
727 obj->setParent(target);
729 QML_END_INSTR(StoreValueSource)
731 QML_BEGIN_INSTR(StoreValueInterceptor)
732 QObject *obj = stack.pop();
733 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
734 QObject *target = stack.at(stack.count() - 1 - instr.owner);
735 QDeclarativeProperty prop =
736 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
737 obj->setParent(target);
739 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
740 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
741 QML_END_INSTR(StoreValueInterceptor)
743 QML_BEGIN_INSTR(StoreObjectQList)
744 QObject *assign = stack.pop();
746 const ListInstance &list = qliststack.top();
747 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
748 QML_END_INSTR(StoreObjectQList)
750 QML_BEGIN_INSTR(AssignObjectList)
751 // This is only used for assigning interfaces
752 QObject *assign = stack.pop();
753 const ListInstance &list = qliststack.top();
755 int type = list.type;
759 const char *iid = QDeclarativeMetaType::interfaceIId(type);
761 ptr = assign->qt_metacast(iid);
763 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line);
766 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
767 QML_END_INSTR(AssignObjectList)
769 QML_BEGIN_INSTR(StoreVariantObject)
770 QObject *assign = stack.pop();
771 QObject *target = stack.top();
772 CLEAN_PROPERTY(target, instr.propertyIndex);
774 QVariant v = QVariant::fromValue(assign);
775 void *a[] = { &v, 0, &status, &flags };
776 QMetaObject::metacall(target, QMetaObject::WriteProperty,
777 instr.propertyIndex, a);
778 QML_END_INSTR(StoreVariantObject)
780 QML_BEGIN_INSTR(StoreInterface)
781 QObject *assign = stack.pop();
782 QObject *target = stack.top();
783 CLEAN_PROPERTY(target, instr.propertyIndex);
785 int coreIdx = instr.propertyIndex;
786 QMetaProperty prop = target->metaObject()->property(coreIdx);
787 int t = prop.userType();
788 const char *iid = QDeclarativeMetaType::interfaceIId(t);
791 void *ptr = assign->qt_metacast(iid);
793 void *a[] = { &ptr, 0, &status, &flags };
794 QMetaObject::metacall(target,
795 QMetaObject::WriteProperty,
802 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line);
803 QML_END_INSTR(StoreInterface)
805 QML_BEGIN_INSTR(FetchAttached)
806 QObject *target = stack.top();
808 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
811 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line);
813 stack.push(qmlObject);
814 QML_END_INSTR(FetchAttached)
816 QML_BEGIN_INSTR(FetchQList)
817 QObject *target = stack.top();
819 qliststack.push(ListInstance(instr.type));
822 a[0] = (void *)&(qliststack.top().qListProperty);
823 QMetaObject::metacall(target, QMetaObject::ReadProperty,
825 QML_END_INSTR(FetchQList)
827 QML_BEGIN_INSTR(FetchObject)
828 QObject *target = stack.top();
831 // NOTE: This assumes a cast to QObject does not alter the
835 QMetaObject::metacall(target, QMetaObject::ReadProperty,
839 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);
842 QML_END_INSTR(FetchObject)
844 QML_BEGIN_INSTR(PopQList)
846 QML_END_INSTR(PopQList)
848 QML_BEGIN_INSTR(Defer)
849 if (instr.deferCount) {
850 QObject *target = stack.top();
851 QDeclarativeData *data =
852 QDeclarativeData::get(target, true);
854 data->deferredComponent = comp;
855 data->deferredIdx = instructionStream - comp->bytecode.constData();
856 instructionStream += instr.deferCount;
860 QML_BEGIN_INSTR(PopFetchedObject)
862 QML_END_INSTR(PopFetchedObject)
864 QML_BEGIN_INSTR(FetchValueType)
865 QObject *target = stack.top();
867 if (instr.bindingSkipList != 0) {
868 // Possibly need to clear bindings
869 QDeclarativeData *targetData = QDeclarativeData::get(target);
871 QDeclarativeAbstractBinding *binding =
872 QDeclarativePropertyPrivate::binding(target, instr.property, -1);
874 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
875 QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
877 } else if (binding) {
878 QDeclarativeValueTypeProxyBinding *proxy =
879 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
880 proxy->removeBindings(instr.bindingSkipList);
885 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
886 valueHandler->read(target, instr.property);
887 stack.push(valueHandler);
888 QML_END_INSTR(FetchValueType)
890 QML_BEGIN_INSTR(PopValueType)
891 QDeclarativeValueType *valueHandler =
892 static_cast<QDeclarativeValueType *>(stack.pop());
893 QObject *target = stack.top();
894 valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
895 QML_END_INSTR(PopValueType)
898 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type());
904 if (!stack.isEmpty()) {
905 delete stack.at(0); // ### What about failures in deferred creation?
910 QDeclarativeEnginePrivate::clear(bindValues);
911 QDeclarativeEnginePrivate::clear(parserStatus);
915 if (bindValues.count)
916 ep->bindValues << bindValues;
917 else if (bindValues.values)
920 if (parserStatus.count)
921 ep->parserStatus << parserStatus;
922 else if (parserStatus.values)
923 parserStatus.clear();
925 Q_ASSERT(stack.count() == 1);
929 bool QDeclarativeVME::isError() const
931 return !vmeErrors.isEmpty();
934 QList<QDeclarativeError> QDeclarativeVME::errors() const
940 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
941 const QBitField &bindings,
942 QList<QDeclarativeError> *errors) const
948 type->create(&rv, &memory, sizeof(QDeclarativeData));
949 QDeclarativeData *ddata = new (memory) QDeclarativeData;
950 ddata->ownMemory = false;
951 QObjectPrivate::get(rv)->declarativeData = ddata;
953 if (typePropertyCache && !ddata->propertyCache) {
954 ddata->propertyCache = typePropertyCache;
955 ddata->propertyCache->addref();
961 return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings);
965 QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
967 if (script->m_loaded)
968 return script->m_value;
970 QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine);
971 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine);
973 bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
975 // Create the script context if required
976 QDeclarativeContextData *ctxt = 0;
978 ctxt = new QDeclarativeContextData;
979 ctxt->isInternal = true;
980 ctxt->url = script->url;
982 // For backward compatibility, if there are no imports, we need to use the
983 // imports from the parent context. See QTBUG-17518.
984 if (!script->importCache->isEmpty()) {
985 ctxt->imports = script->importCache;
987 ctxt->imports = parentCtxt->imports;
991 ctxt->imports->addref();
994 ctxt->setParent(parentCtxt, true);
996 for (int ii = 0; ii < script->scripts.count(); ++ii)
997 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1000 QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
1002 scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()?
1004 scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString()));
1007 scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
1008 QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
1009 scriptContext->pushScope(scope);
1011 scriptEngine->evaluate(script->m_program);
1013 if (scriptEngine->hasUncaughtException()) {
1014 QDeclarativeError error;
1015 QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
1016 enginePriv->warning(error);
1019 scriptEngine->popContext();
1022 script->m_loaded = true;
1023 script->m_value = scope;