/src/declarative/qml/qdeclarativevme.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 1124 lines · 886 code · 189 blank · 49 comment · 99 complexity · ed89d34b36e4e135a4602a26649627e5 MD5 · raw file

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  6. **
  7. ** This file is part of the QtDeclarative module of the Qt Toolkit.
  8. **
  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.
  17. **
  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.
  21. **
  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.
  29. **
  30. ** Other Usage
  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.
  33. **
  34. **
  35. **
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "private/qdeclarativevme_p.h"
  42. #include "private/qdeclarativecompiler_p.h"
  43. #include "private/qdeclarativeboundsignal_p.h"
  44. #include "private/qdeclarativestringconverters_p.h"
  45. #include "private/qmetaobjectbuilder_p.h"
  46. #include "private/qdeclarativedata_p.h"
  47. #include "qdeclarative.h"
  48. #include "private/qdeclarativecustomparser_p.h"
  49. #include "qdeclarativeengine.h"
  50. #include "qdeclarativecontext.h"
  51. #include "qdeclarativecomponent.h"
  52. #include "private/qdeclarativebinding_p.h"
  53. #include "private/qdeclarativeengine_p.h"
  54. #include "private/qdeclarativecomponent_p.h"
  55. #include "private/qdeclarativevmemetaobject_p.h"
  56. #include "private/qdeclarativebinding_p_p.h"
  57. #include "private/qdeclarativecontext_p.h"
  58. #include "private/qdeclarativecompiledbindings_p.h"
  59. #include "private/qdeclarativeglobal_p.h"
  60. #include "qdeclarativescriptstring.h"
  61. #include <QStack>
  62. #include <QWidget>
  63. #include <QColor>
  64. #include <QPointF>
  65. #include <QSizeF>
  66. #include <QRectF>
  67. #include <QtCore/qdebug.h>
  68. #include <QtCore/qvarlengtharray.h>
  69. #include <QtCore/qcoreapplication.h>
  70. #include <QtCore/qdatetime.h>
  71. QT_BEGIN_NAMESPACE
  72. // A simple stack wrapper around QVarLengthArray
  73. template<typename T>
  74. class QDeclarativeVMEStack : private QVarLengthArray<T, 128>
  75. {
  76. private:
  77. typedef QVarLengthArray<T, 128> VLA;
  78. int _index;
  79. public:
  80. inline QDeclarativeVMEStack();
  81. inline bool isEmpty() const;
  82. inline const T &top() const;
  83. inline void push(const T &o);
  84. inline T pop();
  85. inline int count() const;
  86. inline const T &at(int index) const;
  87. };
  88. // We do this so we can forward declare the type in the qdeclarativevme_p.h header
  89. class QDeclarativeVMEObjectStack : public QDeclarativeVMEStack<QObject *> {};
  90. QDeclarativeVME::QDeclarativeVME()
  91. {
  92. }
  93. #define VME_EXCEPTION(desc) \
  94. { \
  95. QDeclarativeError error; \
  96. error.setDescription(desc.trimmed()); \
  97. error.setLine(instr.line); \
  98. error.setUrl(comp->url); \
  99. vmeErrors << error; \
  100. break; \
  101. }
  102. struct ListInstance
  103. {
  104. ListInstance()
  105. : type(0) {}
  106. ListInstance(int t)
  107. : type(t) {}
  108. int type;
  109. QDeclarativeListProperty<void> qListProperty;
  110. };
  111. Q_DECLARE_TYPEINFO(ListInstance, Q_PRIMITIVE_TYPE | Q_MOVABLE_TYPE);
  112. QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp,
  113. int start, int count, const QBitField &bindingSkipList)
  114. {
  115. QDeclarativeVMEObjectStack stack;
  116. if (start == -1) start = 0;
  117. if (count == -1) count = comp->bytecode.count();
  118. return run(stack, ctxt, comp, start, count, bindingSkipList);
  119. }
  120. void QDeclarativeVME::runDeferred(QObject *object)
  121. {
  122. QDeclarativeData *data = QDeclarativeData::get(object);
  123. if (!data || !data->context || !data->deferredComponent)
  124. return;
  125. QDeclarativeContextData *ctxt = data->context;
  126. QDeclarativeCompiledData *comp = data->deferredComponent;
  127. int start = data->deferredIdx + 1;
  128. int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount;
  129. QDeclarativeVMEObjectStack stack;
  130. stack.push(object);
  131. run(stack, ctxt, comp, start, count, QBitField());
  132. }
  133. inline bool fastHasBinding(QObject *o, int index)
  134. {
  135. QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
  136. return ddata && (ddata->bindingBitsSize > index) &&
  137. (ddata->bindingBits[index / 32] & (1 << (index % 32)));
  138. }
  139. static void removeBindingOnProperty(QObject *o, int index)
  140. {
  141. QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
  142. if (binding) binding->destroy();
  143. }
  144. #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
  145. QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack,
  146. QDeclarativeContextData *ctxt,
  147. QDeclarativeCompiledData *comp,
  148. int start, int count,
  149. const QBitField &bindingSkipList)
  150. {
  151. Q_ASSERT(comp);
  152. Q_ASSERT(ctxt);
  153. const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types;
  154. const QList<QString> &primitives = comp->primitives;
  155. const QList<QByteArray> &datas = comp->datas;
  156. const QList<QDeclarativeCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
  157. const QList<int> &intData = comp->intData;
  158. const QList<float> &floatData = comp->floatData;
  159. const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches;
  160. const QList<QDeclarativeParser::Object::ScriptBlock> &scripts = comp->scripts;
  161. const QList<QUrl> &urls = comp->urls;
  162. QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues;
  163. QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus;
  164. QDeclarativeVMEStack<ListInstance> qliststack;
  165. vmeErrors.clear();
  166. QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
  167. int status = -1; //for dbus
  168. QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
  169. QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
  170. for (int ii = start; !isError() && ii < (start + count); ++ii) {
  171. const QDeclarativeInstruction &instr = comp->bytecode.at(ii);
  172. switch(instr.type) {
  173. case QDeclarativeInstruction::Init:
  174. {
  175. if (instr.init.bindingsSize)
  176. bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.init.bindingsSize);
  177. if (instr.init.parserStatusSize)
  178. parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.init.parserStatusSize);
  179. if (instr.init.contextCache != -1)
  180. ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
  181. if (instr.init.compiledBinding != -1)
  182. ctxt->optimizedBindings = new QDeclarativeCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt, comp);
  183. }
  184. break;
  185. case QDeclarativeInstruction::CreateObject:
  186. {
  187. QBitField bindings;
  188. if (instr.create.bindingBits != -1) {
  189. const QByteArray &bits = datas.at(instr.create.bindingBits);
  190. bindings = QBitField((const quint32*)bits.constData(),
  191. bits.size() * 8);
  192. }
  193. if (stack.isEmpty())
  194. bindings = bindings.united(bindingSkipList);
  195. QObject *o =
  196. types.at(instr.create.type).createInstance(ctxt, bindings, &vmeErrors);
  197. if (!o) {
  198. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)));
  199. }
  200. QDeclarativeData *ddata = QDeclarativeData::get(o);
  201. Q_ASSERT(ddata);
  202. if (stack.isEmpty()) {
  203. if (ddata->context) {
  204. Q_ASSERT(ddata->context != ctxt);
  205. Q_ASSERT(ddata->outerContext);
  206. Q_ASSERT(ddata->outerContext != ctxt);
  207. QDeclarativeContextData *c = ddata->context;
  208. while (c->linkedContext) c = c->linkedContext;
  209. c->linkedContext = ctxt;
  210. } else {
  211. ctxt->addObject(o);
  212. }
  213. ddata->ownContext = true;
  214. } else if (!ddata->context) {
  215. ctxt->addObject(o);
  216. }
  217. ddata->setImplicitDestructible();
  218. ddata->outerContext = ctxt;
  219. ddata->lineNumber = instr.line;
  220. ddata->columnNumber = instr.create.column;
  221. if (instr.create.data != -1) {
  222. QDeclarativeCustomParser *customParser =
  223. types.at(instr.create.type).type->customParser();
  224. customParser->setCustomData(o, datas.at(instr.create.data));
  225. }
  226. if (!stack.isEmpty()) {
  227. QObject *parent = stack.top();
  228. if (o->isWidgetType()) {
  229. QWidget *widget = static_cast<QWidget*>(o);
  230. if (parent->isWidgetType()) {
  231. QWidget *parentWidget = static_cast<QWidget*>(parent);
  232. widget->setParent(parentWidget);
  233. } else {
  234. // TODO: parent might be a layout
  235. }
  236. } else {
  237. QDeclarative_setParent_noEvent(o, parent);
  238. }
  239. }
  240. stack.push(o);
  241. }
  242. break;
  243. case QDeclarativeInstruction::CreateSimpleObject:
  244. {
  245. QObject *o = (QObject *)operator new(instr.createSimple.typeSize +
  246. sizeof(QDeclarativeData));
  247. ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeData));
  248. instr.createSimple.create(o);
  249. QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize);
  250. const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.createSimple.type);
  251. if (!ddata->propertyCache && ref.typePropertyCache) {
  252. ddata->propertyCache = ref.typePropertyCache;
  253. ddata->propertyCache->addref();
  254. }
  255. ddata->lineNumber = instr.line;
  256. ddata->columnNumber = instr.createSimple.column;
  257. QObjectPrivate::get(o)->declarativeData = ddata;
  258. ddata->context = ddata->outerContext = ctxt;
  259. ddata->nextContextObject = ctxt->contextObjects;
  260. if (ddata->nextContextObject)
  261. ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
  262. ddata->prevContextObject = &ctxt->contextObjects;
  263. ctxt->contextObjects = ddata;
  264. QObject *parent = stack.top();
  265. QDeclarative_setParent_noEvent(o, parent);
  266. stack.push(o);
  267. }
  268. break;
  269. case QDeclarativeInstruction::SetId:
  270. {
  271. QObject *target = stack.top();
  272. ctxt->setIdProperty(instr.setId.index, target);
  273. }
  274. break;
  275. case QDeclarativeInstruction::SetDefault:
  276. {
  277. ctxt->contextObject = stack.top();
  278. }
  279. break;
  280. case QDeclarativeInstruction::CreateComponent:
  281. {
  282. QDeclarativeComponent *qcomp =
  283. new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count,
  284. stack.isEmpty() ? 0 : stack.top());
  285. QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
  286. Q_ASSERT(ddata);
  287. ctxt->addObject(qcomp);
  288. if (stack.isEmpty())
  289. ddata->ownContext = true;
  290. ddata->setImplicitDestructible();
  291. ddata->outerContext = ctxt;
  292. ddata->lineNumber = instr.line;
  293. ddata->columnNumber = instr.create.column;
  294. QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
  295. stack.push(qcomp);
  296. ii += instr.createComponent.count;
  297. }
  298. break;
  299. case QDeclarativeInstruction::StoreMetaObject:
  300. {
  301. QObject *target = stack.top();
  302. QMetaObject mo;
  303. const QByteArray &metadata = datas.at(instr.storeMeta.data);
  304. QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
  305. const QDeclarativeVMEMetaData *data =
  306. (const QDeclarativeVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
  307. (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
  308. if (instr.storeMeta.propertyCache != -1) {
  309. QDeclarativeData *ddata = QDeclarativeData::get(target, true);
  310. if (ddata->propertyCache) ddata->propertyCache->release();
  311. ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache);
  312. ddata->propertyCache->addref();
  313. }
  314. }
  315. break;
  316. case QDeclarativeInstruction::StoreVariant:
  317. {
  318. QObject *target = stack.top();
  319. CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
  320. // XXX - can be more efficient
  321. QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.storeString.value));
  322. void *a[] = { &v, 0, &status, &flags };
  323. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  324. instr.storeString.propertyIndex, a);
  325. }
  326. break;
  327. case QDeclarativeInstruction::StoreVariantInteger:
  328. {
  329. QObject *target = stack.top();
  330. CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
  331. QVariant v(instr.storeInteger.value);
  332. void *a[] = { &v, 0, &status, &flags };
  333. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  334. instr.storeString.propertyIndex, a);
  335. }
  336. break;
  337. case QDeclarativeInstruction::StoreVariantDouble:
  338. {
  339. QObject *target = stack.top();
  340. CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
  341. QVariant v(instr.storeDouble.value);
  342. void *a[] = { &v, 0, &status, &flags };
  343. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  344. instr.storeString.propertyIndex, a);
  345. }
  346. break;
  347. case QDeclarativeInstruction::StoreVariantBool:
  348. {
  349. QObject *target = stack.top();
  350. CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
  351. QVariant v(instr.storeBool.value);
  352. void *a[] = { &v, 0, &status, &flags };
  353. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  354. instr.storeString.propertyIndex, a);
  355. }
  356. break;
  357. case QDeclarativeInstruction::StoreString:
  358. {
  359. QObject *target = stack.top();
  360. CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
  361. void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags };
  362. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  363. instr.storeString.propertyIndex, a);
  364. }
  365. break;
  366. case QDeclarativeInstruction::StoreUrl:
  367. {
  368. QObject *target = stack.top();
  369. CLEAN_PROPERTY(target, instr.storeUrl.propertyIndex);
  370. void *a[] = { (void *)&urls.at(instr.storeUrl.value), 0, &status, &flags };
  371. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  372. instr.storeUrl.propertyIndex, a);
  373. }
  374. break;
  375. case QDeclarativeInstruction::StoreFloat:
  376. {
  377. QObject *target = stack.top();
  378. CLEAN_PROPERTY(target, instr.storeFloat.propertyIndex);
  379. float f = instr.storeFloat.value;
  380. void *a[] = { &f, 0, &status, &flags };
  381. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  382. instr.storeFloat.propertyIndex, a);
  383. }
  384. break;
  385. case QDeclarativeInstruction::StoreDouble:
  386. {
  387. QObject *target = stack.top();
  388. CLEAN_PROPERTY(target, instr.storeDouble.propertyIndex);
  389. double d = instr.storeDouble.value;
  390. void *a[] = { &d, 0, &status, &flags };
  391. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  392. instr.storeDouble.propertyIndex, a);
  393. }
  394. break;
  395. case QDeclarativeInstruction::StoreBool:
  396. {
  397. QObject *target = stack.top();
  398. CLEAN_PROPERTY(target, instr.storeBool.propertyIndex);
  399. void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags };
  400. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  401. instr.storeBool.propertyIndex, a);
  402. }
  403. break;
  404. case QDeclarativeInstruction::StoreInteger:
  405. {
  406. QObject *target = stack.top();
  407. CLEAN_PROPERTY(target, instr.storeInteger.propertyIndex);
  408. void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags };
  409. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  410. instr.storeInteger.propertyIndex, a);
  411. }
  412. break;
  413. case QDeclarativeInstruction::StoreColor:
  414. {
  415. QObject *target = stack.top();
  416. CLEAN_PROPERTY(target, instr.storeColor.propertyIndex);
  417. QColor c = QColor::fromRgba(instr.storeColor.value);
  418. void *a[] = { &c, 0, &status, &flags };
  419. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  420. instr.storeColor.propertyIndex, a);
  421. }
  422. break;
  423. case QDeclarativeInstruction::StoreDate:
  424. {
  425. QObject *target = stack.top();
  426. CLEAN_PROPERTY(target, instr.storeDate.propertyIndex);
  427. QDate d = QDate::fromJulianDay(instr.storeDate.value);
  428. void *a[] = { &d, 0, &status, &flags };
  429. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  430. instr.storeDate.propertyIndex, a);
  431. }
  432. break;
  433. case QDeclarativeInstruction::StoreTime:
  434. {
  435. QObject *target = stack.top();
  436. CLEAN_PROPERTY(target, instr.storeTime.propertyIndex);
  437. QTime t;
  438. t.setHMS(intData.at(instr.storeTime.valueIndex),
  439. intData.at(instr.storeTime.valueIndex+1),
  440. intData.at(instr.storeTime.valueIndex+2),
  441. intData.at(instr.storeTime.valueIndex+3));
  442. void *a[] = { &t, 0, &status, &flags };
  443. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  444. instr.storeTime.propertyIndex, a);
  445. }
  446. break;
  447. case QDeclarativeInstruction::StoreDateTime:
  448. {
  449. QObject *target = stack.top();
  450. CLEAN_PROPERTY(target, instr.storeDateTime.propertyIndex);
  451. QTime t;
  452. t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
  453. intData.at(instr.storeDateTime.valueIndex+2),
  454. intData.at(instr.storeDateTime.valueIndex+3),
  455. intData.at(instr.storeDateTime.valueIndex+4));
  456. QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
  457. void *a[] = { &dt, 0, &status, &flags };
  458. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  459. instr.storeDateTime.propertyIndex, a);
  460. }
  461. break;
  462. case QDeclarativeInstruction::StorePoint:
  463. {
  464. QObject *target = stack.top();
  465. CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
  466. QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
  467. floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
  468. void *a[] = { &p, 0, &status, &flags };
  469. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  470. instr.storeRealPair.propertyIndex, a);
  471. }
  472. break;
  473. case QDeclarativeInstruction::StorePointF:
  474. {
  475. QObject *target = stack.top();
  476. CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
  477. QPointF p(floatData.at(instr.storeRealPair.valueIndex),
  478. floatData.at(instr.storeRealPair.valueIndex+1));
  479. void *a[] = { &p, 0, &status, &flags };
  480. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  481. instr.storeRealPair.propertyIndex, a);
  482. }
  483. break;
  484. case QDeclarativeInstruction::StoreSize:
  485. {
  486. QObject *target = stack.top();
  487. CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
  488. QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
  489. floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
  490. void *a[] = { &p, 0, &status, &flags };
  491. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  492. instr.storeRealPair.propertyIndex, a);
  493. }
  494. break;
  495. case QDeclarativeInstruction::StoreSizeF:
  496. {
  497. QObject *target = stack.top();
  498. CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
  499. QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
  500. floatData.at(instr.storeRealPair.valueIndex+1));
  501. void *a[] = { &s, 0, &status, &flags };
  502. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  503. instr.storeRealPair.propertyIndex, a);
  504. }
  505. break;
  506. case QDeclarativeInstruction::StoreRect:
  507. {
  508. QObject *target = stack.top();
  509. CLEAN_PROPERTY(target, instr.storeRect.propertyIndex);
  510. QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
  511. floatData.at(instr.storeRect.valueIndex+1),
  512. floatData.at(instr.storeRect.valueIndex+2),
  513. floatData.at(instr.storeRect.valueIndex+3)).toRect();
  514. void *a[] = { &r, 0, &status, &flags };
  515. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  516. instr.storeRect.propertyIndex, a);
  517. }
  518. break;
  519. case QDeclarativeInstruction::StoreRectF:
  520. {
  521. QObject *target = stack.top();
  522. CLEAN_PROPERTY(target, instr.storeRect.propertyIndex);
  523. QRectF r(floatData.at(instr.storeRect.valueIndex),
  524. floatData.at(instr.storeRect.valueIndex+1),
  525. floatData.at(instr.storeRect.valueIndex+2),
  526. floatData.at(instr.storeRect.valueIndex+3));
  527. void *a[] = { &r, 0, &status, &flags };
  528. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  529. instr.storeRect.propertyIndex, a);
  530. }
  531. break;
  532. case QDeclarativeInstruction::StoreVector3D:
  533. {
  534. QObject *target = stack.top();
  535. CLEAN_PROPERTY(target, instr.storeVector3D.propertyIndex);
  536. QVector3D p(floatData.at(instr.storeVector3D.valueIndex),
  537. floatData.at(instr.storeVector3D.valueIndex+1),
  538. floatData.at(instr.storeVector3D.valueIndex+2));
  539. void *a[] = { &p, 0, &status, &flags };
  540. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  541. instr.storeVector3D.propertyIndex, a);
  542. }
  543. break;
  544. case QDeclarativeInstruction::StoreObject:
  545. {
  546. QObject *assignObj = stack.pop();
  547. QObject *target = stack.top();
  548. CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
  549. void *a[] = { (void *)&assignObj, 0, &status, &flags };
  550. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  551. instr.storeObject.propertyIndex, a);
  552. }
  553. break;
  554. case QDeclarativeInstruction::AssignCustomType:
  555. {
  556. QObject *target = stack.top();
  557. CLEAN_PROPERTY(target, instr.assignCustomType.propertyIndex);
  558. QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
  559. const QString &primitive = primitives.at(data.index);
  560. QDeclarativeMetaType::StringConverter converter =
  561. QDeclarativeMetaType::customStringConverter(data.type);
  562. QVariant v = (*converter)(primitive);
  563. QMetaProperty prop =
  564. target->metaObject()->property(instr.assignCustomType.propertyIndex);
  565. if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
  566. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())));
  567. void *a[] = { (void *)v.data(), 0, &status, &flags };
  568. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  569. instr.assignCustomType.propertyIndex, a);
  570. }
  571. break;
  572. case QDeclarativeInstruction::AssignSignalObject:
  573. {
  574. // XXX optimize
  575. QObject *assign = stack.pop();
  576. QObject *target = stack.top();
  577. int sigIdx = instr.assignSignalObject.signal;
  578. const QByteArray &pr = datas.at(sigIdx);
  579. QDeclarativeProperty prop(target, QString::fromUtf8(pr));
  580. if (prop.type() & QDeclarativeProperty::SignalProperty) {
  581. QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
  582. if (method.signature() == 0)
  583. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())));
  584. if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
  585. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())));
  586. QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
  587. } else {
  588. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)));
  589. }
  590. }
  591. break;
  592. case QDeclarativeInstruction::StoreSignal:
  593. {
  594. QObject *target = stack.top();
  595. QObject *context = stack.at(stack.count() - 1 - instr.storeSignal.context);
  596. QMetaMethod signal = target->metaObject()->method(instr.storeSignal.signalIndex);
  597. QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
  598. QDeclarativeExpression *expr =
  599. new QDeclarativeExpression(ctxt, context, primitives.at(instr.storeSignal.value));
  600. expr->setSourceLocation(comp->name, instr.line);
  601. static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.storeSignal.name);
  602. bs->setExpression(expr);
  603. }
  604. break;
  605. case QDeclarativeInstruction::StoreImportedScript:
  606. {
  607. ctxt->addImportedScript(scripts.at(instr.storeScript.value));
  608. }
  609. break;
  610. case QDeclarativeInstruction::StoreScriptString:
  611. {
  612. QObject *target = stack.top();
  613. QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope);
  614. QDeclarativeScriptString ss;
  615. ss.setContext(ctxt->asQDeclarativeContext());
  616. ss.setScopeObject(scope);
  617. ss.setScript(primitives.at(instr.storeScriptString.value));
  618. void *a[] = { &ss, 0, &status, &flags };
  619. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  620. instr.storeScriptString.propertyIndex, a);
  621. }
  622. break;
  623. case QDeclarativeInstruction::BeginObject:
  624. {
  625. QObject *target = stack.top();
  626. QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
  627. parserStatus.append(status);
  628. status->d = &parserStatus.values[parserStatus.count - 1];
  629. status->classBegin();
  630. }
  631. break;
  632. case QDeclarativeInstruction::StoreBinding:
  633. case QDeclarativeInstruction::StoreBindingOnAlias:
  634. {
  635. QObject *target =
  636. stack.at(stack.count() - 1 - instr.assignBinding.owner);
  637. QObject *context =
  638. stack.at(stack.count() - 1 - instr.assignBinding.context);
  639. QDeclarativeProperty mp =
  640. QDeclarativePropertyPrivate::restore(datas.at(instr.assignBinding.property), target, ctxt);
  641. int coreIndex = mp.index();
  642. if ((stack.count() - instr.assignBinding.owner) == 1 && bindingSkipList.testBit(coreIndex))
  643. break;
  644. QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
  645. bindValues.append(bind);
  646. bind->m_mePtr = &bindValues.values[bindValues.count - 1];
  647. bind->setTarget(mp);
  648. if (instr.type == QDeclarativeInstruction::StoreBindingOnAlias) {
  649. QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
  650. if (old) { old->destroy(); }
  651. } else {
  652. bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
  653. }
  654. }
  655. break;
  656. case QDeclarativeInstruction::StoreCompiledBinding:
  657. {
  658. QObject *target =
  659. stack.at(stack.count() - 1 - instr.assignBinding.owner);
  660. QObject *scope =
  661. stack.at(stack.count() - 1 - instr.assignBinding.context);
  662. int property = instr.assignBinding.property;
  663. if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
  664. break;
  665. QDeclarativeAbstractBinding *binding =
  666. ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property);
  667. bindValues.append(binding);
  668. binding->m_mePtr = &bindValues.values[bindValues.count - 1];
  669. binding->addToObject(target, property);
  670. }
  671. break;
  672. case QDeclarativeInstruction::StoreValueSource:
  673. {
  674. QObject *obj = stack.pop();
  675. QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.assignValueSource.castValue);
  676. QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner);
  677. QDeclarativeProperty prop =
  678. QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueSource.property), target, ctxt);
  679. obj->setParent(target);
  680. vs->setTarget(prop);
  681. }
  682. break;
  683. case QDeclarativeInstruction::StoreValueInterceptor:
  684. {
  685. QObject *obj = stack.pop();
  686. QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue);
  687. QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner);
  688. QDeclarativeProperty prop =
  689. QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueInterceptor.property), target, ctxt);
  690. obj->setParent(target);
  691. vi->setTarget(prop);
  692. QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
  693. mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
  694. }
  695. break;
  696. case QDeclarativeInstruction::StoreObjectQList:
  697. {
  698. QObject *assign = stack.pop();
  699. const ListInstance &list = qliststack.top();
  700. list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
  701. }
  702. break;
  703. case QDeclarativeInstruction::AssignObjectList:
  704. {
  705. // This is only used for assigning interfaces
  706. QObject *assign = stack.pop();
  707. const ListInstance &list = qliststack.top();
  708. int type = list.type;
  709. void *ptr = 0;
  710. const char *iid = QDeclarativeMetaType::interfaceIId(type);
  711. if (iid)
  712. ptr = assign->qt_metacast(iid);
  713. if (!ptr)
  714. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"));
  715. list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
  716. }
  717. break;
  718. case QDeclarativeInstruction::StoreVariantObject:
  719. {
  720. QObject *assign = stack.pop();
  721. QObject *target = stack.top();
  722. CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
  723. QVariant v = QVariant::fromValue(assign);
  724. void *a[] = { &v, 0, &status, &flags };
  725. QMetaObject::metacall(target, QMetaObject::WriteProperty,
  726. instr.storeObject.propertyIndex, a);
  727. }
  728. break;
  729. case QDeclarativeInstruction::StoreInterface:
  730. {
  731. QObject *assign = stack.pop();
  732. QObject *target = stack.top();
  733. CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
  734. int coreIdx = instr.storeObject.propertyIndex;
  735. QMetaProperty prop = target->metaObject()->property(coreIdx);
  736. int t = prop.userType();
  737. const char *iid = QDeclarativeMetaType::interfaceIId(t);
  738. bool ok = false;
  739. if (iid) {
  740. void *ptr = assign->qt_metacast(iid);
  741. if (ptr) {
  742. void *a[] = { &ptr, 0, &status, &flags };
  743. QMetaObject::metacall(target,
  744. QMetaObject::WriteProperty,
  745. coreIdx, a);
  746. ok = true;
  747. }
  748. }
  749. if (!ok)
  750. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"));
  751. }
  752. break;
  753. case QDeclarativeInstruction::FetchAttached:
  754. {
  755. QObject *target = stack.top();
  756. QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target);
  757. if (!qmlObject)
  758. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"));
  759. stack.push(qmlObject);
  760. }
  761. break;
  762. case QDeclarativeInstruction::FetchQList:
  763. {
  764. QObject *target = stack.top();
  765. qliststack.push(ListInstance(instr.fetchQmlList.type));
  766. void *a[1];
  767. a[0] = (void *)&(qliststack.top().qListProperty);
  768. QMetaObject::metacall(target, QMetaObject::ReadProperty,
  769. instr.fetchQmlList.property, a);
  770. }
  771. break;
  772. case QDeclarativeInstruction::FetchObject:
  773. {
  774. QObject *target = stack.top();
  775. QObject *obj = 0;
  776. // NOTE: This assumes a cast to QObject does not alter the
  777. // object pointer
  778. void *a[1];
  779. a[0] = &obj;
  780. QMetaObject::metacall(target, QMetaObject::ReadProperty,
  781. instr.fetch.property, a);
  782. if (!obj)
  783. VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name())));
  784. stack.push(obj);
  785. }
  786. break;
  787. case QDeclarativeInstruction::PopQList:
  788. {
  789. qliststack.pop();
  790. }
  791. break;
  792. case QDeclarativeInstruction::Defer:
  793. {
  794. if (instr.defer.deferCount) {
  795. QObject *target = stack.top();
  796. QDeclarativeData *data =
  797. QDeclarativeData::get(target, true);
  798. comp->addref();
  799. data->deferredComponent = comp;
  800. data->deferredIdx = ii;
  801. ii += instr.defer.deferCount;
  802. }
  803. }
  804. break;
  805. case QDeclarativeInstruction::PopFetchedObject:
  806. {
  807. stack.pop();
  808. }
  809. break;
  810. case QDeclarativeInstruction::FetchValueType:
  811. {
  812. QObject *target = stack.top();
  813. if (instr.fetchValue.bindingSkipList != 0) {
  814. // Possibly need to clear bindings
  815. QDeclarativeData *targetData = QDeclarativeData::get(target);
  816. if (targetData) {
  817. QDeclarativeAbstractBinding *binding =
  818. QDeclarativePropertyPrivate::binding(target, instr.fetchValue.property, -1);
  819. if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
  820. QDeclarativePropertyPrivate::setBinding(target, instr.fetchValue.property, -1, 0);
  821. binding->destroy();
  822. } else if (binding) {
  823. QDeclarativeValueTypeProxyBinding *proxy =
  824. static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
  825. proxy->removeBindings(instr.fetchValue.bindingSkipList);
  826. }
  827. }
  828. }
  829. QDeclarativeValueType *valueHandler = ep->valueTypes[instr.fetchValue.type];
  830. valueHandler->read(target, instr.fetchValue.property);
  831. stack.push(valueHandler);
  832. }
  833. break;
  834. case QDeclarativeInstruction::PopValueType:
  835. {
  836. QDeclarativeValueType *valueHandler =
  837. static_cast<QDeclarativeValueType *>(stack.pop());
  838. QObject *target = stack.top();
  839. valueHandler->write(target, instr.fetchValue.property,
  840. QDeclarativePropertyPrivate::BypassInterceptor);
  841. }
  842. break;
  843. default:
  844. qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", instr.type);
  845. break;
  846. }
  847. }
  848. if (isError()) {
  849. if (!stack.isEmpty()) {
  850. delete stack.at(0); // ### What about failures in deferred creation?
  851. } else {
  852. ctxt->destroy();
  853. }
  854. QDeclarativeEnginePrivate::clear(bindValues);
  855. QDeclarativeEnginePrivate::clear(parserStatus);
  856. return 0;
  857. }
  858. if (bindValues.count)
  859. ep->bindValues << bindValues;
  860. else if (bindValues.values)
  861. bindValues.clear();
  862. if (parserStatus.count)
  863. ep->parserStatus << parserStatus;
  864. else if (parserStatus.values)
  865. parserStatus.clear();
  866. Q_ASSERT(stack.count() == 1);
  867. return stack.top();
  868. }
  869. bool QDeclarativeVME::isError() const
  870. {
  871. return !vmeErrors.isEmpty();
  872. }
  873. QList<QDeclarativeError> QDeclarativeVME::errors() const
  874. {
  875. return vmeErrors;
  876. }
  877. QObject *
  878. QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
  879. const QBitField &bindings,
  880. QList<QDeclarativeError> *errors) const
  881. {
  882. if (type) {
  883. QObject *rv = 0;
  884. void *memory = 0;
  885. type->create(&rv, &memory, sizeof(QDeclarativeData));
  886. QDeclarativeData *ddata = new (memory) QDeclarativeData;
  887. ddata->ownMemory = false;
  888. QObjectPrivate::get(rv)->declarativeData = ddata;
  889. if (typePropertyCache && !ddata->propertyCache) {
  890. ddata->propertyCache = typePropertyCache;
  891. ddata->propertyCache->addref();
  892. }
  893. return rv;
  894. } else {
  895. Q_ASSERT(component);
  896. return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, -1, 0, errors, bindings);
  897. }
  898. }
  899. template<typename T>
  900. QDeclarativeVMEStack<T>::QDeclarativeVMEStack()
  901. : _index(-1)
  902. {
  903. }
  904. template<typename T>
  905. bool QDeclarativeVMEStack<T>::isEmpty() const {
  906. return _index == -1;
  907. }
  908. template<typename T>
  909. const T &QDeclarativeVMEStack<T>::top() const {
  910. return at(_index);
  911. }
  912. template<typename T>
  913. void QDeclarativeVMEStack<T>::push(const T &o) {
  914. _index++;
  915. Q_ASSERT(_index <= VLA::size());
  916. if (_index == VLA::size())
  917. VLA::append(o);
  918. else
  919. VLA::data()[_index] = o;
  920. }
  921. template<typename T>
  922. T QDeclarativeVMEStack<T>::pop() {
  923. Q_ASSERT(_index >= 0);
  924. --_index;
  925. return VLA::data()[_index + 1];
  926. }
  927. template<typename T>
  928. int QDeclarativeVMEStack<T>::count() const {
  929. return _index + 1;
  930. }
  931. template<typename T>
  932. const T &QDeclarativeVMEStack<T>::at(int index) const {
  933. return VLA::data()[index];
  934. }
  935. QT_END_NAMESPACE