/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 3105 lines · 2349 code · 583 blank · 173 comment · 167 complexity · 5701bd03e8cf76f0470690b49807748f 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 test suite 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 <qtest.h>
  42. #include <QtDeclarative/qdeclarativecomponent.h>
  43. #include <QtDeclarative/qdeclarativeengine.h>
  44. #include <QtDeclarative/qdeclarativeexpression.h>
  45. #include <QtDeclarative/qdeclarativecontext.h>
  46. #include <QtCore/qfileinfo.h>
  47. #include <QtCore/qdebug.h>
  48. #include <QtDeclarative/private/qdeclarativeguard_p.h>
  49. #include <QtCore/qdir.h>
  50. #include <QtCore/qnumeric.h>
  51. #include <private/qdeclarativeengine_p.h>
  52. #include <private/qdeclarativeglobalscriptclass_p.h>
  53. #include <private/qscriptdeclarativeclass_p.h>
  54. #include "testtypes.h"
  55. #include "testhttpserver.h"
  56. #include "../../../shared/util.h"
  57. #ifdef Q_OS_SYMBIAN
  58. // In Symbian OS test data is located in applications private dir
  59. #define SRCDIR "."
  60. #endif
  61. /*
  62. This test covers evaluation of ECMAScript expressions and bindings from within
  63. QML. This does not include static QML language issues.
  64. Static QML language issues are covered in qmllanguage
  65. */
  66. inline QUrl TEST_FILE(const QString &filename)
  67. {
  68. QFileInfo fileInfo(__FILE__);
  69. return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
  70. }
  71. inline QUrl TEST_FILE(const char *filename)
  72. {
  73. return TEST_FILE(QLatin1String(filename));
  74. }
  75. class tst_qdeclarativeecmascript : public QObject
  76. {
  77. Q_OBJECT
  78. public:
  79. tst_qdeclarativeecmascript() {}
  80. private slots:
  81. void initTestCase();
  82. void assignBasicTypes();
  83. void idShortcutInvalidates();
  84. void boolPropertiesEvaluateAsBool();
  85. void methods();
  86. void signalAssignment();
  87. void bindingLoop();
  88. void basicExpressions();
  89. void basicExpressions_data();
  90. void arrayExpressions();
  91. void contextPropertiesTriggerReeval();
  92. void objectPropertiesTriggerReeval();
  93. void deferredProperties();
  94. void deferredPropertiesErrors();
  95. void extensionObjects();
  96. void overrideExtensionProperties();
  97. void attachedProperties();
  98. void enums();
  99. void valueTypeFunctions();
  100. void constantsOverrideBindings();
  101. void outerBindingOverridesInnerBinding();
  102. void aliasPropertyAndBinding();
  103. void nonExistentAttachedObject();
  104. void scope();
  105. void signalParameterTypes();
  106. void objectsCompareAsEqual();
  107. void dynamicCreation_data();
  108. void dynamicCreation();
  109. void dynamicDestruction();
  110. void objectToString();
  111. void selfDeletingBinding();
  112. void extendedObjectPropertyLookup();
  113. void scriptErrors();
  114. void functionErrors();
  115. void propertyAssignmentErrors();
  116. void signalTriggeredBindings();
  117. void listProperties();
  118. void exceptionClearsOnReeval();
  119. void exceptionSlotProducesWarning();
  120. void exceptionBindingProducesWarning();
  121. void transientErrors();
  122. void shutdownErrors();
  123. void compositePropertyType();
  124. void jsObject();
  125. void undefinedResetsProperty();
  126. void listToVariant();
  127. void multiEngineObject();
  128. void deletedObject();
  129. void attachedPropertyScope();
  130. void scriptConnect();
  131. void scriptDisconnect();
  132. void ownership();
  133. void cppOwnershipReturnValue();
  134. void ownershipCustomReturnValue();
  135. void qlistqobjectMethods();
  136. void strictlyEquals();
  137. void compiled();
  138. void numberAssignment();
  139. void propertySplicing();
  140. void signalWithUnknownTypes();
  141. void bug1();
  142. void bug2();
  143. void dynamicCreationCrash();
  144. void regExpBug();
  145. void nullObjectBinding();
  146. void deletedEngine();
  147. void libraryScriptAssert();
  148. void variantsAssignedUndefined();
  149. void qtbug_9792();
  150. void qtcreatorbug_1289();
  151. void noSpuriousWarningsAtShutdown();
  152. void canAssignNullToQObject();
  153. void functionAssignment_fromBinding();
  154. void functionAssignment_fromJS();
  155. void functionAssignment_fromJS_data();
  156. void functionAssignmentfromJS_invalid();
  157. void eval();
  158. void function();
  159. void qtbug_10696();
  160. void qtbug_11606();
  161. void qtbug_11600();
  162. void nonscriptable();
  163. void deleteLater();
  164. void in();
  165. void sharedAttachedObject();
  166. void objectName();
  167. void writeRemovesBinding();
  168. void aliasBindingsAssignCorrectly();
  169. void aliasBindingsOverrideTarget();
  170. void aliasWritesOverrideBindings();
  171. void pushCleanContext();
  172. void realToInt();
  173. void qtbug_20648();
  174. void include();
  175. void callQtInvokables();
  176. void invokableObjectArg();
  177. void invokableObjectRet();
  178. void revisionErrors();
  179. void revision();
  180. private:
  181. QDeclarativeEngine engine;
  182. };
  183. void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
  184. void tst_qdeclarativeecmascript::assignBasicTypes()
  185. {
  186. {
  187. QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
  188. MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
  189. QVERIFY(object != 0);
  190. QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
  191. QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
  192. QCOMPARE(object->stringProperty(), QString("Hello World!"));
  193. QCOMPARE(object->uintProperty(), uint(10));
  194. QCOMPARE(object->intProperty(), -19);
  195. QCOMPARE((float)object->realProperty(), float(23.2));
  196. QCOMPARE((float)object->doubleProperty(), float(-19.75));
  197. QCOMPARE((float)object->floatProperty(), float(8.5));
  198. QCOMPARE(object->colorProperty(), QColor("red"));
  199. QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
  200. QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
  201. QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
  202. QCOMPARE(object->pointProperty(), QPoint(99,13));
  203. QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
  204. QCOMPARE(object->sizeProperty(), QSize(99, 13));
  205. QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
  206. QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
  207. QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
  208. QCOMPARE(object->boolProperty(), true);
  209. QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
  210. QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
  211. QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
  212. delete object;
  213. }
  214. {
  215. QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
  216. MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
  217. QVERIFY(object != 0);
  218. QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
  219. QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
  220. QCOMPARE(object->stringProperty(), QString("Hello World!"));
  221. QCOMPARE(object->uintProperty(), uint(10));
  222. QCOMPARE(object->intProperty(), -19);
  223. QCOMPARE((float)object->realProperty(), float(23.2));
  224. QCOMPARE((float)object->doubleProperty(), float(-19.75));
  225. QCOMPARE((float)object->floatProperty(), float(8.5));
  226. QCOMPARE(object->colorProperty(), QColor("red"));
  227. QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
  228. QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
  229. QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
  230. QCOMPARE(object->pointProperty(), QPoint(99,13));
  231. QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
  232. QCOMPARE(object->sizeProperty(), QSize(99, 13));
  233. QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
  234. QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
  235. QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
  236. QCOMPARE(object->boolProperty(), true);
  237. QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
  238. QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
  239. QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
  240. delete object;
  241. }
  242. }
  243. void tst_qdeclarativeecmascript::idShortcutInvalidates()
  244. {
  245. {
  246. QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
  247. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  248. QVERIFY(object != 0);
  249. QVERIFY(object->objectProperty() != 0);
  250. delete object->objectProperty();
  251. QVERIFY(object->objectProperty() == 0);
  252. }
  253. {
  254. QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
  255. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  256. QVERIFY(object != 0);
  257. QVERIFY(object->objectProperty() != 0);
  258. delete object->objectProperty();
  259. QVERIFY(object->objectProperty() == 0);
  260. }
  261. }
  262. void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
  263. {
  264. {
  265. QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
  266. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  267. QVERIFY(object != 0);
  268. QCOMPARE(object->stringProperty(), QLatin1String("pass"));
  269. }
  270. {
  271. QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
  272. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  273. QVERIFY(object != 0);
  274. QCOMPARE(object->stringProperty(), QLatin1String("pass"));
  275. }
  276. }
  277. void tst_qdeclarativeecmascript::signalAssignment()
  278. {
  279. {
  280. QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
  281. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  282. QVERIFY(object != 0);
  283. QCOMPARE(object->string(), QString());
  284. emit object->basicSignal();
  285. QCOMPARE(object->string(), QString("pass"));
  286. }
  287. {
  288. QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
  289. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  290. QVERIFY(object != 0);
  291. QCOMPARE(object->string(), QString());
  292. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  293. QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
  294. }
  295. }
  296. void tst_qdeclarativeecmascript::methods()
  297. {
  298. {
  299. QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
  300. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  301. QVERIFY(object != 0);
  302. QCOMPARE(object->methodCalled(), false);
  303. QCOMPARE(object->methodIntCalled(), false);
  304. emit object->basicSignal();
  305. QCOMPARE(object->methodCalled(), true);
  306. QCOMPARE(object->methodIntCalled(), false);
  307. }
  308. {
  309. QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
  310. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  311. QVERIFY(object != 0);
  312. QCOMPARE(object->methodCalled(), false);
  313. QCOMPARE(object->methodIntCalled(), false);
  314. emit object->basicSignal();
  315. QCOMPARE(object->methodCalled(), false);
  316. QCOMPARE(object->methodIntCalled(), true);
  317. }
  318. {
  319. QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
  320. QObject *object = component.create();
  321. QVERIFY(object != 0);
  322. QCOMPARE(object->property("test").toInt(), 19);
  323. }
  324. {
  325. QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
  326. QObject *object = component.create();
  327. QVERIFY(object != 0);
  328. QCOMPARE(object->property("test").toInt(), 19);
  329. QCOMPARE(object->property("test2").toInt(), 17);
  330. QCOMPARE(object->property("test3").toInt(), 16);
  331. }
  332. {
  333. QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
  334. QObject *object = component.create();
  335. QVERIFY(object != 0);
  336. QCOMPARE(object->property("test").toInt(), 9);
  337. }
  338. }
  339. void tst_qdeclarativeecmascript::bindingLoop()
  340. {
  341. QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
  342. QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
  343. QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
  344. QObject *object = component.create();
  345. QVERIFY(object != 0);
  346. }
  347. void tst_qdeclarativeecmascript::basicExpressions_data()
  348. {
  349. QTest::addColumn<QString>("expression");
  350. QTest::addColumn<QVariant>("result");
  351. QTest::addColumn<bool>("nest");
  352. QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
  353. QTest::newRow("Context property") << "a" << QVariant(1944) << false;
  354. QTest::newRow("Context property") << "a" << QVariant(1944) << true;
  355. QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
  356. QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
  357. QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
  358. QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
  359. QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
  360. QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
  361. QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
  362. QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
  363. QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
  364. QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
  365. QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
  366. QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
  367. QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
  368. QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
  369. QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
  370. QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
  371. }
  372. void tst_qdeclarativeecmascript::basicExpressions()
  373. {
  374. QFETCH(QString, expression);
  375. QFETCH(QVariant, result);
  376. QFETCH(bool, nest);
  377. MyQmlObject object1;
  378. MyQmlObject object2;
  379. MyQmlObject object3;
  380. MyDefaultObject1 default1;
  381. MyDefaultObject3 default3;
  382. object1.setStringProperty("Object1");
  383. object2.setStringProperty("Object2");
  384. object3.setStringProperty("Object3");
  385. QDeclarativeContext context(engine.rootContext());
  386. QDeclarativeContext nestedContext(&context);
  387. context.setContextObject(&default1);
  388. context.setContextProperty("a", QVariant(1944));
  389. context.setContextProperty("b", QVariant("Milk"));
  390. context.setContextProperty("object", &object1);
  391. context.setContextProperty("objectOverride", &object2);
  392. nestedContext.setContextObject(&default3);
  393. nestedContext.setContextProperty("b", QVariant("Cow"));
  394. nestedContext.setContextProperty("objectOverride", &object3);
  395. nestedContext.setContextProperty("millipedeLegs", QVariant(100));
  396. MyExpression expr(nest?&nestedContext:&context, expression);
  397. QCOMPARE(expr.evaluate(), result);
  398. }
  399. void tst_qdeclarativeecmascript::arrayExpressions()
  400. {
  401. QObject obj1;
  402. QObject obj2;
  403. QObject obj3;
  404. QDeclarativeContext context(engine.rootContext());
  405. context.setContextProperty("a", &obj1);
  406. context.setContextProperty("b", &obj2);
  407. context.setContextProperty("c", &obj3);
  408. MyExpression expr(&context, "[a, b, c, 10]");
  409. QVariant result = expr.evaluate();
  410. QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
  411. QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
  412. QCOMPARE(list.count(), 4);
  413. QCOMPARE(list.at(0), &obj1);
  414. QCOMPARE(list.at(1), &obj2);
  415. QCOMPARE(list.at(2), &obj3);
  416. QCOMPARE(list.at(3), (QObject *)0);
  417. }
  418. // Tests that modifying a context property will reevaluate expressions
  419. void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
  420. {
  421. QDeclarativeContext context(engine.rootContext());
  422. MyQmlObject object1;
  423. MyQmlObject object2;
  424. MyQmlObject *object3 = new MyQmlObject;
  425. object1.setStringProperty("Hello");
  426. object2.setStringProperty("World");
  427. context.setContextProperty("testProp", QVariant(1));
  428. context.setContextProperty("testObj", &object1);
  429. context.setContextProperty("testObj2", object3);
  430. {
  431. MyExpression expr(&context, "testProp + 1");
  432. QCOMPARE(expr.changed, false);
  433. QCOMPARE(expr.evaluate(), QVariant(2));
  434. context.setContextProperty("testProp", QVariant(2));
  435. QCOMPARE(expr.changed, true);
  436. QCOMPARE(expr.evaluate(), QVariant(3));
  437. }
  438. {
  439. MyExpression expr(&context, "testProp + testProp + testProp");
  440. QCOMPARE(expr.changed, false);
  441. QCOMPARE(expr.evaluate(), QVariant(6));
  442. context.setContextProperty("testProp", QVariant(4));
  443. QCOMPARE(expr.changed, true);
  444. QCOMPARE(expr.evaluate(), QVariant(12));
  445. }
  446. {
  447. MyExpression expr(&context, "testObj.stringProperty");
  448. QCOMPARE(expr.changed, false);
  449. QCOMPARE(expr.evaluate(), QVariant("Hello"));
  450. context.setContextProperty("testObj", &object2);
  451. QCOMPARE(expr.changed, true);
  452. QCOMPARE(expr.evaluate(), QVariant("World"));
  453. }
  454. {
  455. MyExpression expr(&context, "testObj.stringProperty /**/");
  456. QCOMPARE(expr.changed, false);
  457. QCOMPARE(expr.evaluate(), QVariant("World"));
  458. context.setContextProperty("testObj", &object1);
  459. QCOMPARE(expr.changed, true);
  460. QCOMPARE(expr.evaluate(), QVariant("Hello"));
  461. }
  462. {
  463. MyExpression expr(&context, "testObj2");
  464. QCOMPARE(expr.changed, false);
  465. QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
  466. }
  467. }
  468. void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
  469. {
  470. QDeclarativeContext context(engine.rootContext());
  471. MyQmlObject object1;
  472. MyQmlObject object2;
  473. MyQmlObject object3;
  474. context.setContextProperty("testObj", &object1);
  475. object1.setStringProperty(QLatin1String("Hello"));
  476. object2.setStringProperty(QLatin1String("Dog"));
  477. object3.setStringProperty(QLatin1String("Cat"));
  478. {
  479. MyExpression expr(&context, "testObj.stringProperty");
  480. QCOMPARE(expr.changed, false);
  481. QCOMPARE(expr.evaluate(), QVariant("Hello"));
  482. object1.setStringProperty(QLatin1String("World"));
  483. QCOMPARE(expr.changed, true);
  484. QCOMPARE(expr.evaluate(), QVariant("World"));
  485. }
  486. {
  487. MyExpression expr(&context, "testObj.objectProperty.stringProperty");
  488. QCOMPARE(expr.changed, false);
  489. QCOMPARE(expr.evaluate(), QVariant());
  490. object1.setObjectProperty(&object2);
  491. QCOMPARE(expr.changed, true);
  492. expr.changed = false;
  493. QCOMPARE(expr.evaluate(), QVariant("Dog"));
  494. object1.setObjectProperty(&object3);
  495. QCOMPARE(expr.changed, true);
  496. expr.changed = false;
  497. QCOMPARE(expr.evaluate(), QVariant("Cat"));
  498. object1.setObjectProperty(0);
  499. QCOMPARE(expr.changed, true);
  500. expr.changed = false;
  501. QCOMPARE(expr.evaluate(), QVariant());
  502. object1.setObjectProperty(&object3);
  503. QCOMPARE(expr.changed, true);
  504. expr.changed = false;
  505. QCOMPARE(expr.evaluate(), QVariant("Cat"));
  506. object3.setStringProperty("Donkey");
  507. QCOMPARE(expr.changed, true);
  508. expr.changed = false;
  509. QCOMPARE(expr.evaluate(), QVariant("Donkey"));
  510. }
  511. }
  512. void tst_qdeclarativeecmascript::deferredProperties()
  513. {
  514. QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
  515. MyDeferredObject *object =
  516. qobject_cast<MyDeferredObject *>(component.create());
  517. QVERIFY(object != 0);
  518. QCOMPARE(object->value(), 0);
  519. QVERIFY(object->objectProperty() == 0);
  520. QVERIFY(object->objectProperty2() != 0);
  521. qmlExecuteDeferred(object);
  522. QCOMPARE(object->value(), 10);
  523. QVERIFY(object->objectProperty() != 0);
  524. MyQmlObject *qmlObject =
  525. qobject_cast<MyQmlObject *>(object->objectProperty());
  526. QVERIFY(qmlObject != 0);
  527. QCOMPARE(qmlObject->value(), 10);
  528. object->setValue(19);
  529. QCOMPARE(qmlObject->value(), 19);
  530. }
  531. // Check errors on deferred properties are correctly emitted
  532. void tst_qdeclarativeecmascript::deferredPropertiesErrors()
  533. {
  534. QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
  535. MyDeferredObject *object =
  536. qobject_cast<MyDeferredObject *>(component.create());
  537. QVERIFY(object != 0);
  538. QCOMPARE(object->value(), 0);
  539. QVERIFY(object->objectProperty() == 0);
  540. QVERIFY(object->objectProperty2() == 0);
  541. QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
  542. QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
  543. qmlExecuteDeferred(object);
  544. delete object;
  545. }
  546. void tst_qdeclarativeecmascript::extensionObjects()
  547. {
  548. QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
  549. MyExtendedObject *object =
  550. qobject_cast<MyExtendedObject *>(component.create());
  551. QVERIFY(object != 0);
  552. QCOMPARE(object->baseProperty(), 13);
  553. QCOMPARE(object->coreProperty(), 9);
  554. object->setProperty("extendedProperty", QVariant(11));
  555. object->setProperty("baseExtendedProperty", QVariant(92));
  556. QCOMPARE(object->coreProperty(), 11);
  557. QCOMPARE(object->baseProperty(), 92);
  558. MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
  559. QVERIFY(nested);
  560. QCOMPARE(nested->baseProperty(), 13);
  561. QCOMPARE(nested->coreProperty(), 9);
  562. nested->setProperty("extendedProperty", QVariant(11));
  563. nested->setProperty("baseExtendedProperty", QVariant(92));
  564. QCOMPARE(nested->coreProperty(), 11);
  565. QCOMPARE(nested->baseProperty(), 92);
  566. }
  567. void tst_qdeclarativeecmascript::overrideExtensionProperties()
  568. {
  569. QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
  570. OverrideDefaultPropertyObject *object =
  571. qobject_cast<OverrideDefaultPropertyObject *>(component.create());
  572. QVERIFY(object != 0);
  573. QVERIFY(object->secondProperty() != 0);
  574. QVERIFY(object->firstProperty() == 0);
  575. }
  576. void tst_qdeclarativeecmascript::attachedProperties()
  577. {
  578. {
  579. QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
  580. QObject *object = component.create();
  581. QVERIFY(object != 0);
  582. QCOMPARE(object->property("a").toInt(), 19);
  583. QCOMPARE(object->property("b").toInt(), 19);
  584. QCOMPARE(object->property("c").toInt(), 19);
  585. QCOMPARE(object->property("d").toInt(), 19);
  586. }
  587. {
  588. QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
  589. QObject *object = component.create();
  590. QVERIFY(object != 0);
  591. QCOMPARE(object->property("a").toInt(), 26);
  592. QCOMPARE(object->property("b").toInt(), 26);
  593. QCOMPARE(object->property("c").toInt(), 26);
  594. QCOMPARE(object->property("d").toInt(), 26);
  595. }
  596. {
  597. QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
  598. QObject *object = component.create();
  599. QVERIFY(object != 0);
  600. QMetaObject::invokeMethod(object, "writeValue2");
  601. MyQmlAttachedObject *attached =
  602. qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
  603. QVERIFY(attached != 0);
  604. QCOMPARE(attached->value2(), 9);
  605. }
  606. }
  607. void tst_qdeclarativeecmascript::enums()
  608. {
  609. // Existent enums
  610. {
  611. QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
  612. QObject *object = component.create();
  613. QVERIFY(object != 0);
  614. QCOMPARE(object->property("a").toInt(), 0);
  615. QCOMPARE(object->property("b").toInt(), 1);
  616. QCOMPARE(object->property("c").toInt(), 2);
  617. QCOMPARE(object->property("d").toInt(), 3);
  618. QCOMPARE(object->property("e").toInt(), 0);
  619. QCOMPARE(object->property("f").toInt(), 1);
  620. QCOMPARE(object->property("g").toInt(), 2);
  621. QCOMPARE(object->property("h").toInt(), 3);
  622. QCOMPARE(object->property("i").toInt(), 19);
  623. QCOMPARE(object->property("j").toInt(), 19);
  624. }
  625. // Non-existent enums
  626. {
  627. QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
  628. QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
  629. QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
  630. QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
  631. QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
  632. QObject *object = component.create();
  633. QVERIFY(object != 0);
  634. QCOMPARE(object->property("a").toInt(), 0);
  635. QCOMPARE(object->property("b").toInt(), 0);
  636. }
  637. }
  638. void tst_qdeclarativeecmascript::valueTypeFunctions()
  639. {
  640. QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
  641. MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
  642. QVERIFY(obj != 0);
  643. QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
  644. QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
  645. }
  646. /*
  647. Tests that writing a constant to a property with a binding on it disables the
  648. binding.
  649. */
  650. void tst_qdeclarativeecmascript::constantsOverrideBindings()
  651. {
  652. // From ECMAScript
  653. {
  654. QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
  655. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  656. QVERIFY(object != 0);
  657. QCOMPARE(object->property("c2").toInt(), 0);
  658. object->setProperty("c1", QVariant(9));
  659. QCOMPARE(object->property("c2").toInt(), 9);
  660. emit object->basicSignal();
  661. QCOMPARE(object->property("c2").toInt(), 13);
  662. object->setProperty("c1", QVariant(8));
  663. QCOMPARE(object->property("c2").toInt(), 13);
  664. }
  665. // During construction
  666. {
  667. QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
  668. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  669. QVERIFY(object != 0);
  670. QCOMPARE(object->property("c1").toInt(), 0);
  671. QCOMPARE(object->property("c2").toInt(), 10);
  672. object->setProperty("c1", QVariant(9));
  673. QCOMPARE(object->property("c1").toInt(), 9);
  674. QCOMPARE(object->property("c2").toInt(), 10);
  675. }
  676. #if 0
  677. // From C++
  678. {
  679. QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
  680. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  681. QVERIFY(object != 0);
  682. QCOMPARE(object->property("c2").toInt(), 0);
  683. object->setProperty("c1", QVariant(9));
  684. QCOMPARE(object->property("c2").toInt(), 9);
  685. object->setProperty("c2", QVariant(13));
  686. QCOMPARE(object->property("c2").toInt(), 13);
  687. object->setProperty("c1", QVariant(7));
  688. QCOMPARE(object->property("c1").toInt(), 7);
  689. QCOMPARE(object->property("c2").toInt(), 13);
  690. }
  691. #endif
  692. // Using an alias
  693. {
  694. QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
  695. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  696. QVERIFY(object != 0);
  697. QCOMPARE(object->property("c1").toInt(), 0);
  698. QCOMPARE(object->property("c3").toInt(), 10);
  699. object->setProperty("c1", QVariant(9));
  700. QCOMPARE(object->property("c1").toInt(), 9);
  701. QCOMPARE(object->property("c3").toInt(), 10);
  702. }
  703. }
  704. /*
  705. Tests that assigning a binding to a property that already has a binding causes
  706. the original binding to be disabled.
  707. */
  708. void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
  709. {
  710. QDeclarativeComponent component(&engine,
  711. TEST_FILE("outerBindingOverridesInnerBinding.qml"));
  712. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  713. QVERIFY(object != 0);
  714. QCOMPARE(object->property("c1").toInt(), 0);
  715. QCOMPARE(object->property("c2").toInt(), 0);
  716. QCOMPARE(object->property("c3").toInt(), 0);
  717. object->setProperty("c1", QVariant(9));
  718. QCOMPARE(object->property("c1").toInt(), 9);
  719. QCOMPARE(object->property("c2").toInt(), 0);
  720. QCOMPARE(object->property("c3").toInt(), 0);
  721. object->setProperty("c3", QVariant(8));
  722. QCOMPARE(object->property("c1").toInt(), 9);
  723. QCOMPARE(object->property("c2").toInt(), 8);
  724. QCOMPARE(object->property("c3").toInt(), 8);
  725. }
  726. /*
  727. Access a non-existent attached object.
  728. Tests for a regression where this used to crash.
  729. */
  730. void tst_qdeclarativeecmascript::nonExistentAttachedObject()
  731. {
  732. QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
  733. QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
  734. QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
  735. QObject *object = component.create();
  736. QVERIFY(object != 0);
  737. }
  738. void tst_qdeclarativeecmascript::scope()
  739. {
  740. {
  741. QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
  742. QObject *object = component.create();
  743. QVERIFY(object != 0);
  744. QCOMPARE(object->property("test1").toInt(), 1);
  745. QCOMPARE(object->property("test2").toInt(), 2);
  746. QCOMPARE(object->property("test3").toString(), QString("1Test"));
  747. QCOMPARE(object->property("test4").toString(), QString("2Test"));
  748. QCOMPARE(object->property("test5").toInt(), 1);
  749. QCOMPARE(object->property("test6").toInt(), 1);
  750. QCOMPARE(object->property("test7").toInt(), 2);
  751. QCOMPARE(object->property("test8").toInt(), 2);
  752. QCOMPARE(object->property("test9").toInt(), 1);
  753. QCOMPARE(object->property("test10").toInt(), 3);
  754. }
  755. {
  756. QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
  757. QObject *object = component.create();
  758. QVERIFY(object != 0);
  759. QCOMPARE(object->property("test1").toInt(), 19);
  760. QCOMPARE(object->property("test2").toInt(), 19);
  761. QCOMPARE(object->property("test3").toInt(), 14);
  762. QCOMPARE(object->property("test4").toInt(), 14);
  763. QCOMPARE(object->property("test5").toInt(), 24);
  764. QCOMPARE(object->property("test6").toInt(), 24);
  765. }
  766. {
  767. QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
  768. QObject *object = component.create();
  769. QVERIFY(object != 0);
  770. QCOMPARE(object->property("test1").toBool(), true);
  771. QCOMPARE(object->property("test2").toBool(), true);
  772. QCOMPARE(object->property("test3").toBool(), true);
  773. }
  774. // Signal argument scope
  775. {
  776. QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
  777. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  778. QVERIFY(object != 0);
  779. QCOMPARE(object->property("test").toInt(), 0);
  780. QCOMPARE(object->property("test2").toString(), QString());
  781. emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
  782. QCOMPARE(object->property("test").toInt(), 13);
  783. QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
  784. delete object;
  785. }
  786. }
  787. /*
  788. Tests that "any" type passes through a synthesized signal parameter. This
  789. is essentially a test of QDeclarativeMetaType::copy()
  790. */
  791. void tst_qdeclarativeecmascript::signalParameterTypes()
  792. {
  793. QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
  794. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  795. QVERIFY(object != 0);
  796. emit object->basicSignal();
  797. QCOMPARE(object->property("intProperty").toInt(), 10);
  798. QCOMPARE(object->property("realProperty").toReal(), 19.2);
  799. QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
  800. QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
  801. QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
  802. QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
  803. }
  804. /*
  805. Test that two JS objects for the same QObject compare as equal.
  806. */
  807. void tst_qdeclarativeecmascript::objectsCompareAsEqual()
  808. {
  809. QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
  810. QObject *object = component.create();
  811. QVERIFY(object != 0);
  812. QCOMPARE(object->property("test1").toBool(), true);
  813. QCOMPARE(object->property("test2").toBool(), true);
  814. QCOMPARE(object->property("test3").toBool(), true);
  815. QCOMPARE(object->property("test4").toBool(), true);
  816. QCOMPARE(object->property("test5").toBool(), true);
  817. }
  818. /*
  819. Confirm bindings and alias properties can coexist.
  820. Tests for a regression where the binding would not reevaluate.
  821. */
  822. void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
  823. {
  824. QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
  825. QObject *object = component.create();
  826. QVERIFY(object != 0);
  827. QCOMPARE(object->property("c2").toInt(), 3);
  828. QCOMPARE(object->property("c3").toInt(), 3);
  829. object->setProperty("c2", QVariant(19));
  830. QCOMPARE(object->property("c2").toInt(), 19);
  831. QCOMPARE(object->property("c3").toInt(), 19);
  832. }
  833. void tst_qdeclarativeecmascript::dynamicCreation_data()
  834. {
  835. QTest::addColumn<QString>("method");
  836. QTest::addColumn<QString>("createdName");
  837. QTest::newRow("One") << "createOne" << "objectOne";
  838. QTest::newRow("Two") << "createTwo" << "objectTwo";
  839. QTest::newRow("Three") << "createThree" << "objectThree";
  840. }
  841. /*
  842. Test using createQmlObject to dynamically generate an item
  843. Also using createComponent is tested.
  844. */
  845. void tst_qdeclarativeecmascript::dynamicCreation()
  846. {
  847. QFETCH(QString, method);
  848. QFETCH(QString, createdName);
  849. QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
  850. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  851. QVERIFY(object != 0);
  852. QMetaObject::invokeMethod(object, method.toUtf8());
  853. QObject *created = object->objectProperty();
  854. QVERIFY(created);
  855. QCOMPARE(created->objectName(), createdName);
  856. }
  857. /*
  858. Tests the destroy function
  859. */
  860. void tst_qdeclarativeecmascript::dynamicDestruction()
  861. {
  862. QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
  863. QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
  864. QVERIFY(object != 0);
  865. QDeclarativeGuard<QObject> createdQmlObject = 0;
  866. QMetaObject::invokeMethod(object, "create");
  867. createdQmlObject = object->objectProperty();
  868. QVERIFY(createdQmlObject);
  869. QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
  870. QMetaObject::invokeMethod(object, "killOther");
  871. QVERIFY(createdQmlObject);
  872. QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
  873. QVERIFY(createdQmlObject);
  874. for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
  875. if (createdQmlObject) {
  876. QTest::qWait(100);
  877. QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
  878. }
  879. }
  880. QVERIFY(!createdQmlObject);
  881. QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
  882. QMetaObject::invokeMethod(object, "killMe");
  883. QVERIFY(object);
  884. QTest::qWait(0);
  885. QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
  886. QVERIFY(!object);
  887. }
  888. /*
  889. tests that id.toString() works
  890. */
  891. void tst_qdeclarativeecmascript::objectToString()
  892. {
  893. QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
  894. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  895. QVERIFY(object != 0);
  896. QMetaObject::invokeMethod(object, "testToString");
  897. QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
  898. QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
  899. }
  900. /*
  901. Tests bindings that indirectly cause their own deletion work.
  902. This test is best run under valgrind to ensure no invalid memory access occur.
  903. */
  904. void tst_qdeclarativeecmascript::selfDeletingBinding()
  905. {
  906. {
  907. QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
  908. QObject *object = component.create();
  909. QVERIFY(object != 0);
  910. object->setProperty("triggerDelete", true);
  911. }
  912. {
  913. QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
  914. QObject *object = component.create();
  915. QVERIFY(object != 0);
  916. object->setProperty("triggerDelete", true);
  917. }
  918. }
  919. /*
  920. Test that extended object properties can be accessed.
  921. This test a regression where this used to crash. The issue was specificially
  922. for extended objects that did not include a synthesized meta object (so non-root
  923. and no synthesiszed properties).
  924. */
  925. void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
  926. {
  927. QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
  928. QObject *object = component.create();
  929. QVERIFY(object != 0);
  930. }
  931. /*
  932. Test file/lineNumbers for binding/Script errors.
  933. */
  934. void tst_qdeclarativeecmascript::scriptErrors()
  935. {
  936. QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
  937. QString url = component.url().toString();
  938. QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
  939. QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
  940. QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
  941. QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
  942. QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
  943. QString warning6 = url + ":7: Unable to assign [undefined] to int x";
  944. QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
  945. QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
  946. QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
  947. QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
  948. QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
  949. QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
  950. QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
  951. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  952. QVERIFY(object != 0);
  953. QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
  954. emit object->basicSignal();
  955. QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
  956. emit object->anotherBasicSignal();
  957. QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
  958. emit object->thirdBasicSignal();
  959. }
  960. /*
  961. Test file/lineNumbers for inline functions.
  962. */
  963. void tst_qdeclarativeecmascript::functionErrors()
  964. {
  965. QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
  966. QString url = component.url().toString();
  967. QString warning = url + ":5: Error: Invalid write to global property \"a\"";
  968. QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
  969. QObject *object = component.create();
  970. QVERIFY(object != 0);
  971. delete object;
  972. }
  973. /*
  974. Test various errors that can occur when assigning a property from script
  975. */
  976. void tst_qdeclarativeecmascript::propertyAssignmentErrors()
  977. {
  978. QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
  979. QString url = component.url().toString();
  980. QString warning1 = url + ":11:Error: Cannot assign [undefined] to int";
  981. QString warning2 = url + ":17:Error: Cannot assign QString to int";
  982. QTest::ignoreMessage(QtDebugMsg, warning1.toLatin1().constData());
  983. QTest::ignoreMessage(QtDebugMsg, warning2.toLatin1().constData());
  984. QObject *object = component.create();
  985. QVERIFY(object != 0);
  986. delete object;
  987. }
  988. /*
  989. Test bindings still work when the reeval is triggered from within
  990. a signal script.
  991. */
  992. void tst_qdeclarativeecmascript::signalTriggeredBindings()
  993. {
  994. QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
  995. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  996. QVERIFY(object != 0);
  997. QCOMPARE(object->property("base").toReal(), 50.);
  998. QCOMPARE(object->property("test1").toReal(), 50.);
  999. QCOMPARE(object->property("test2").toReal(), 50.);
  1000. object->basicSignal();
  1001. QCOMPARE(object->property("base").toReal(), 200.);
  1002. QCOMPARE(object->property("test1").toReal(), 200.);
  1003. QCOMPARE(object->property("test2").toReal(), 200.);
  1004. object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
  1005. QCOMPARE(object->property("base").toReal(), 400.);
  1006. QCOMPARE(object->property("test1").toReal(), 400.);
  1007. QCOMPARE(object->property("test2").toReal(), 400.);
  1008. }
  1009. /*
  1010. Test that list properties can be iterated from ECMAScript
  1011. */
  1012. void tst_qdeclarativeecmascript::listProperties()
  1013. {
  1014. QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
  1015. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  1016. QVERIFY(object != 0);
  1017. QCOMPARE(object->property("test1").toInt(), 21);
  1018. QCOMPARE(object->property("test2").toInt(), 2);
  1019. QCOMPARE(object->property("test3").toBool(), true);
  1020. QCOMPARE(object->property("test4").toBool(), true);
  1021. }
  1022. void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
  1023. {
  1024. QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
  1025. QString url = component.url().toString();
  1026. QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object.";
  1027. QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
  1028. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  1029. QVERIFY(object != 0);
  1030. QCOMPARE(object->property("test").toBool(), false);
  1031. MyQmlObject object2;
  1032. MyQmlObject object3;
  1033. object2.setObjectProperty(&object3);
  1034. object->setObjectProperty(&object2);
  1035. QCOMPARE(object->property("test").toBool(), true);
  1036. }
  1037. void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
  1038. {
  1039. QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
  1040. QString url = component.url().toString();
  1041. QString warning = component.url().toString() + ":6: Error: JS exception";
  1042. QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
  1043. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  1044. QVERIFY(object != 0);
  1045. }
  1046. void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
  1047. {
  1048. QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
  1049. QString url = component.url().toString();
  1050. QString warning = component.url().toString() + ":5: Error: JS exception";
  1051. QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
  1052. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  1053. QVERIFY(object != 0);
  1054. }
  1055. static int transientErrorsMsgCount = 0;
  1056. static void transientErrorsMsgHandler(QtMsgType, const char *)
  1057. {
  1058. ++transientErrorsMsgCount;
  1059. }
  1060. // Check that transient binding errors are not displayed
  1061. void tst_qdeclarativeecmascript::transientErrors()
  1062. {
  1063. {
  1064. QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
  1065. transientErrorsMsgCount = 0;
  1066. QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
  1067. QObject *object = component.create();
  1068. QVERIFY(object != 0);
  1069. qInstallMsgHandler(old);
  1070. QCOMPARE(transientErrorsMsgCount, 0);
  1071. }
  1072. // One binding erroring multiple times, but then resolving
  1073. {
  1074. QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
  1075. transientErrorsMsgCount = 0;
  1076. QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
  1077. QObject *object = component.create();
  1078. QVERIFY(object != 0);
  1079. qInstallMsgHandler(old);
  1080. QCOMPARE(transientErrorsMsgCount, 0);
  1081. }
  1082. }
  1083. // Check that errors during shutdown are minimized
  1084. void tst_qdeclarativeecmascript::shutdownErrors()
  1085. {
  1086. QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
  1087. QObject *object = component.create();
  1088. QVERIFY(object != 0);
  1089. transientErrorsMsgCount = 0;
  1090. QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
  1091. delete object;
  1092. qInstallMsgHandler(old);
  1093. QCOMPARE(transientErrorsMsgCount, 0);
  1094. }
  1095. void tst_qdeclarativeecmascript::compositePropertyType()
  1096. {
  1097. QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
  1098. QTest::ignoreMessage(QtDebugMsg, "hello world");
  1099. QObject *object = qobject_cast<QObject *>(component.create());
  1100. delete object;
  1101. }
  1102. // QTBUG-5759
  1103. void tst_qdeclarativeecmascript::jsObject()
  1104. {
  1105. QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
  1106. QObject *object = component.create();
  1107. QVERIFY(object != 0);
  1108. QCOMPARE(object->property("test").toInt(), 92);
  1109. delete object;
  1110. }
  1111. void tst_qdeclarativeecmascript::undefinedResetsProperty()
  1112. {
  1113. {
  1114. QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
  1115. QObject *object = component.create();
  1116. QVERIFY(object != 0);
  1117. QCOMPARE(object->property("resettableProperty").toInt(), 92);
  1118. object->setProperty("setUndefined", true);
  1119. QCOMPARE(object->property("resettableProperty").toInt(), 13);
  1120. object->setProperty("setUndefined", false);
  1121. QCOMPARE(object->property("resettableProperty").toInt(), 92);
  1122. delete object;
  1123. }
  1124. {
  1125. QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
  1126. QObject *object = component.create();
  1127. QVERIFY(object != 0);
  1128. QCOMPARE(object->property("resettableProperty").toInt(), 19);
  1129. QMetaObject::invokeMethod(object, "doReset");
  1130. QCOMPARE(object->property("resettableProperty").toInt(), 13);
  1131. delete object;
  1132. }
  1133. }
  1134. // QTBUG-6781
  1135. void tst_qdeclarativeecmascript::bug1()
  1136. {
  1137. QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
  1138. QObject *object = component.create();
  1139. QVERIFY(object != 0);
  1140. QCOMPARE(object->property("test").toInt(), 14);
  1141. object->setProperty("a", 11);
  1142. QCOMPARE(object->property("test").toInt(), 3);
  1143. object->setProperty("b", true);
  1144. QCOMPARE(object->property("test").toInt(), 9);
  1145. delete object;
  1146. }
  1147. void tst_qdeclarativeecmascript::bug2()
  1148. {
  1149. QDeclarativeComponent component(&engine);
  1150. component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
  1151. QObject *object = component.create();
  1152. QVERIFY(object != 0);
  1153. delete object;
  1154. }
  1155. // Don't crash in createObject when the component has errors.
  1156. void tst_qdeclarativeecmascript::dynamicCreationCrash()
  1157. {
  1158. QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
  1159. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  1160. QVERIFY(object != 0);
  1161. QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
  1162. QMetaObject::invokeMethod(object, "dontCrash");
  1163. QObject *created = object->objectProperty();
  1164. QVERIFY(created == 0);
  1165. }
  1166. //QTBUG-9367
  1167. void tst_qdeclarativeecmascript::regExpBug()
  1168. {
  1169. QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
  1170. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  1171. QVERIFY(object != 0);
  1172. QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
  1173. }
  1174. void tst_qdeclarativeecmascript::callQtInvokables()
  1175. {
  1176. MyInvokableObject o;
  1177. QDeclarativeEngine qmlengine;
  1178. QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
  1179. QScriptEngine *engine = &ep->scriptEngine;
  1180. QStringList names; QList<QScriptValue> values;
  1181. names << QLatin1String("object"); values << ep->objectClass->newQObject(&o);
  1182. names << QLatin1String("undefined"); values << engine->undefinedValue();
  1183. ep->globalClass->explicitSetProperty(names, values);
  1184. // Non-existent methods
  1185. o.reset();
  1186. QCOMPARE(engine->evaluate("object.method_nonexistent()").isError(), true);
  1187. QCOMPARE(o.error(), false);
  1188. QCOMPARE(o.invoked(), -1);
  1189. QCOMPARE(o.actuals().count(), 0);
  1190. o.reset();
  1191. QCOMPARE(engine->evaluate("object.method_nonexistent(10, 11)").isError(), true);
  1192. QCOMPARE(o.error(), false);
  1193. QCOMPARE(o.invoked(), -1);
  1194. QCOMPARE(o.actuals().count(), 0);
  1195. // Insufficient arguments
  1196. o.reset();
  1197. QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
  1198. QCOMPARE(o.error(), false);
  1199. QCOMPARE(o.invoked(), -1);
  1200. QCOMPARE(o.actuals().count(), 0);
  1201. o.reset();
  1202. QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
  1203. QCOMPARE(o.error(), false);
  1204. QCOMPARE(o.invoked(), -1);
  1205. QCOMPARE(o.actuals().count(), 0);
  1206. // Excessive arguments
  1207. o.reset();
  1208. QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
  1209. QCOMPARE(o.error(), false);
  1210. QCOMPARE(o.invoked(), 8);
  1211. QCOMPARE(o.actuals().count(), 1);
  1212. QCOMPARE(o.actuals().at(0), QVariant(10));
  1213. o.reset();
  1214. QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
  1215. QCOMPARE(o.error(), false);
  1216. QCOMPARE(o.invoked(), 9);
  1217. QCOMPARE(o.actuals().count(), 2);
  1218. QCOMPARE(o.actuals().at(0), QVariant(10));
  1219. QCOMPARE(o.actuals().at(1), QVariant(11));
  1220. // Test return types
  1221. o.reset();
  1222. QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
  1223. QCOMPARE(o.error(), false);
  1224. QCOMPARE(o.invoked(), 0);
  1225. QCOMPARE(o.actuals().count(), 0);
  1226. o.reset();
  1227. QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
  1228. QCOMPARE(o.error(), false);
  1229. QCOMPARE(o.invoked(), 1);
  1230. QCOMPARE(o.actuals().count(), 0);
  1231. o.reset();
  1232. QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.75)));
  1233. QCOMPARE(o.error(), false);
  1234. QCOMPARE(o.invoked(), 2);
  1235. QCOMPARE(o.actuals().count(), 0);
  1236. o.reset();
  1237. {
  1238. QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
  1239. QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
  1240. QCOMPARE(o.error(), false);
  1241. QCOMPARE(o.invoked(), 3);
  1242. QCOMPARE(o.actuals().count(), 0);
  1243. }
  1244. o.reset();
  1245. {
  1246. QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
  1247. QVERIFY(ret.isQObject());
  1248. QCOMPARE(ret.toQObject(), (QObject *)&o);
  1249. QCOMPARE(o.error(), false);
  1250. QCOMPARE(o.invoked(), 4);
  1251. QCOMPARE(o.actuals().count(), 0);
  1252. }
  1253. o.reset();
  1254. QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
  1255. QCOMPARE(o.error(), false);
  1256. QCOMPARE(o.invoked(), 5);
  1257. QCOMPARE(o.actuals().count(), 0);
  1258. o.reset();
  1259. {
  1260. QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
  1261. QVERIFY(ret.isString());
  1262. QCOMPARE(ret.toString(), QString("Hello world"));
  1263. QCOMPARE(o.error(), false);
  1264. QCOMPARE(o.invoked(), 6);
  1265. QCOMPARE(o.actuals().count(), 0);
  1266. }
  1267. o.reset();
  1268. QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
  1269. QCOMPARE(o.error(), false);
  1270. QCOMPARE(o.invoked(), 7);
  1271. QCOMPARE(o.actuals().count(), 0);
  1272. // Test arg types
  1273. o.reset();
  1274. QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
  1275. QCOMPARE(o.error(), false);
  1276. QCOMPARE(o.invoked(), 8);
  1277. QCOMPARE(o.actuals().count(), 1);
  1278. QCOMPARE(o.actuals().at(0), QVariant(94));
  1279. o.reset();
  1280. QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
  1281. QCOMPARE(o.error(), false);
  1282. QCOMPARE(o.invoked(), 8);
  1283. QCOMPARE(o.actuals().count(), 1);
  1284. QCOMPARE(o.actuals().at(0), QVariant(94));
  1285. o.reset();
  1286. QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
  1287. QCOMPARE(o.error(), false);
  1288. QCOMPARE(o.invoked(), 8);
  1289. QCOMPARE(o.actuals().count(), 1);
  1290. QCOMPARE(o.actuals().at(0), QVariant(0));
  1291. o.reset();
  1292. QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
  1293. QCOMPARE(o.error(), false);
  1294. QCOMPARE(o.invoked(), 8);
  1295. QCOMPARE(o.actuals().count(), 1);
  1296. QCOMPARE(o.actuals().at(0), QVariant(0));
  1297. o.reset();
  1298. QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
  1299. QCOMPARE(o.error(), false);
  1300. QCOMPARE(o.invoked(), 8);
  1301. QCOMPARE(o.actuals().count(), 1);
  1302. QCOMPARE(o.actuals().at(0), QVariant(0));
  1303. o.reset();
  1304. QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
  1305. QCOMPARE(o.error(), false);
  1306. QCOMPARE(o.invoked(), 8);
  1307. QCOMPARE(o.actuals().count(), 1);
  1308. QCOMPARE(o.actuals().at(0), QVariant(0));
  1309. o.reset();
  1310. QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
  1311. QCOMPARE(o.error(), false);
  1312. QCOMPARE(o.invoked(), 9);
  1313. QCOMPARE(o.actuals().count(), 2);
  1314. QCOMPARE(o.actuals().at(0), QVariant(122));
  1315. QCOMPARE(o.actuals().at(1), QVariant(9));
  1316. o.reset();
  1317. QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
  1318. QCOMPARE(o.error(), false);
  1319. QCOMPARE(o.invoked(), 10);
  1320. QCOMPARE(o.actuals().count(), 1);
  1321. QCOMPARE(o.actuals().at(0), QVariant(94.3));
  1322. o.reset();
  1323. QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
  1324. QCOMPARE(o.error(), false);
  1325. QCOMPARE(o.invoked(), 10);
  1326. QCOMPARE(o.actuals().count(), 1);
  1327. QCOMPARE(o.actuals().at(0), QVariant(94.3));
  1328. o.reset();
  1329. QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
  1330. QCOMPARE(o.error(), false);
  1331. QCOMPARE(o.invoked(), 10);
  1332. QCOMPARE(o.actuals().count(), 1);
  1333. QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
  1334. o.reset();
  1335. QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
  1336. QCOMPARE(o.error(), false);
  1337. QCOMPARE(o.invoked(), 10);
  1338. QCOMPARE(o.actuals().count(), 1);
  1339. QCOMPARE(o.actuals().at(0), QVariant(0));
  1340. o.reset();
  1341. QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
  1342. QCOMPARE(o.error(), false);
  1343. QCOMPARE(o.invoked(), 10);
  1344. QCOMPARE(o.actuals().count(), 1);
  1345. QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
  1346. o.reset();
  1347. QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
  1348. QCOMPARE(o.error(), false);
  1349. QCOMPARE(o.invoked(), 10);
  1350. QCOMPARE(o.actuals().count(), 1);
  1351. QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
  1352. o.reset();
  1353. QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
  1354. QCOMPARE(o.error(), false);
  1355. QCOMPARE(o.invoked(), 11);
  1356. QCOMPARE(o.actuals().count(), 1);
  1357. QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
  1358. o.reset();
  1359. QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
  1360. QCOMPARE(o.error(), false);
  1361. QCOMPARE(o.invoked(), 11);
  1362. QCOMPARE(o.actuals().count(), 1);
  1363. QCOMPARE(o.actuals().at(0), QVariant("19"));
  1364. o.reset();
  1365. {
  1366. QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
  1367. QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
  1368. QCOMPARE(o.error(), false);
  1369. QCOMPARE(o.invoked(), 11);
  1370. QCOMPARE(o.actuals().count(), 1);
  1371. QCOMPARE(o.actuals().at(0), QVariant(expected));
  1372. }
  1373. o.reset();
  1374. QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
  1375. QCOMPARE(o.error(), false);
  1376. QCOMPARE(o.invoked(), 11);
  1377. QCOMPARE(o.actuals().count(), 1);
  1378. QCOMPARE(o.actuals().at(0), QVariant(QString()));
  1379. o.reset();
  1380. QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
  1381. QCOMPARE(o.error(), false);
  1382. QCOMPARE(o.invoked(), 11);
  1383. QCOMPARE(o.actuals().count(), 1);
  1384. QCOMPARE(o.actuals().at(0), QVariant(QString()));
  1385. o.reset();
  1386. QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
  1387. QCOMPARE(o.error(), false);
  1388. QCOMPARE(o.invoked(), 12);
  1389. QCOMPARE(o.actuals().count(), 1);
  1390. QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
  1391. o.reset();
  1392. QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
  1393. QCOMPARE(o.error(), false);
  1394. QCOMPARE(o.invoked(), 12);
  1395. QCOMPARE(o.actuals().count(), 1);
  1396. QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
  1397. o.reset();
  1398. QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
  1399. QCOMPARE(o.error(), false);
  1400. QCOMPARE(o.invoked(), 12);
  1401. QCOMPARE(o.actuals().count(), 1);
  1402. QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
  1403. o.reset();
  1404. QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
  1405. QCOMPARE(o.error(), false);
  1406. QCOMPARE(o.invoked(), 12);
  1407. QCOMPARE(o.actuals().count(), 1);
  1408. QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
  1409. o.reset();
  1410. QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
  1411. QCOMPARE(o.error(), false);
  1412. QCOMPARE(o.invoked(), 12);
  1413. QCOMPARE(o.actuals().count(), 1);
  1414. QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
  1415. o.reset();
  1416. QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
  1417. QCOMPARE(o.error(), false);
  1418. QCOMPARE(o.invoked(), 12);
  1419. QCOMPARE(o.actuals().count(), 1);
  1420. QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
  1421. o.reset();
  1422. QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
  1423. QCOMPARE(o.error(), false);
  1424. QCOMPARE(o.invoked(), 13);
  1425. QCOMPARE(o.actuals().count(), 1);
  1426. QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
  1427. o.reset();
  1428. QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
  1429. QCOMPARE(o.error(), false);
  1430. QCOMPARE(o.invoked(), 13);
  1431. QCOMPARE(o.actuals().count(), 1);
  1432. QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
  1433. o.reset();
  1434. QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
  1435. QCOMPARE(o.error(), false);
  1436. QCOMPARE(o.invoked(), 13);
  1437. QCOMPARE(o.actuals().count(), 1);
  1438. QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
  1439. o.reset();
  1440. QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
  1441. QCOMPARE(o.error(), false);
  1442. QCOMPARE(o.invoked(), 13);
  1443. QCOMPARE(o.actuals().count(), 1);
  1444. QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
  1445. o.reset();
  1446. QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
  1447. QCOMPARE(o.error(), false);
  1448. QCOMPARE(o.invoked(), 13);
  1449. QCOMPARE(o.actuals().count(), 1);
  1450. QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
  1451. o.reset();
  1452. QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
  1453. QCOMPARE(o.error(), false);
  1454. QCOMPARE(o.invoked(), 14);
  1455. QCOMPARE(o.actuals().count(), 1);
  1456. QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
  1457. o.reset();
  1458. QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
  1459. QCOMPARE(o.error(), false);
  1460. QCOMPARE(o.invoked(), 14);
  1461. QCOMPARE(o.actuals().count(), 1);
  1462. QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
  1463. o.reset();
  1464. QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
  1465. QCOMPARE(o.error(), false);
  1466. QCOMPARE(o.invoked(), 14);
  1467. QCOMPARE(o.actuals().count(), 1);
  1468. QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
  1469. o.reset();
  1470. QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
  1471. QCOMPARE(o.error(), false);
  1472. QCOMPARE(o.invoked(), 14);
  1473. QCOMPARE(o.actuals().count(), 1);
  1474. QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
  1475. o.reset();
  1476. QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
  1477. QCOMPARE(o.error(), false);
  1478. QCOMPARE(o.invoked(), 15);
  1479. QCOMPARE(o.actuals().count(), 2);
  1480. QCOMPARE(o.actuals().at(0), QVariant(4));
  1481. QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
  1482. o.reset();
  1483. QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
  1484. QCOMPARE(o.error(), false);
  1485. QCOMPARE(o.invoked(), 15);
  1486. QCOMPARE(o.actuals().count(), 2);
  1487. QCOMPARE(o.actuals().at(0), QVariant(8));
  1488. QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
  1489. o.reset();
  1490. QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
  1491. QCOMPARE(o.error(), false);
  1492. QCOMPARE(o.invoked(), 15);
  1493. QCOMPARE(o.actuals().count(), 2);
  1494. QCOMPARE(o.actuals().at(0), QVariant(3));
  1495. QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
  1496. o.reset();
  1497. QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
  1498. QCOMPARE(o.error(), false);
  1499. QCOMPARE(o.invoked(), 15);
  1500. QCOMPARE(o.actuals().count(), 2);
  1501. QCOMPARE(o.actuals().at(0), QVariant(44));
  1502. QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
  1503. o.reset();
  1504. QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
  1505. QCOMPARE(o.error(), false);
  1506. QCOMPARE(o.invoked(), -1);
  1507. QCOMPARE(o.actuals().count(), 0);
  1508. o.reset();
  1509. QCOMPARE(engine->evaluate("object.method_overload(10)").isUndefined(), true);
  1510. QCOMPARE(o.error(), false);
  1511. QCOMPARE(o.invoked(), 16);
  1512. QCOMPARE(o.actuals().count(), 1);
  1513. QCOMPARE(o.actuals().at(0), QVariant(10));
  1514. o.reset();
  1515. QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
  1516. QCOMPARE(o.error(), false);
  1517. QCOMPARE(o.invoked(), 17);
  1518. QCOMPARE(o.actuals().count(), 2);
  1519. QCOMPARE(o.actuals().at(0), QVariant(10));
  1520. QCOMPARE(o.actuals().at(1), QVariant(11));
  1521. o.reset();
  1522. QCOMPARE(engine->evaluate("object.method_overload(\"Hello\")").isUndefined(), true);
  1523. QCOMPARE(o.error(), false);
  1524. QCOMPARE(o.invoked(), 18);
  1525. QCOMPARE(o.actuals().count(), 1);
  1526. QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
  1527. o.reset();
  1528. QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
  1529. QCOMPARE(o.error(), false);
  1530. QCOMPARE(o.invoked(), 19);
  1531. QCOMPARE(o.actuals().count(), 1);
  1532. QCOMPARE(o.actuals().at(0), QVariant(9));
  1533. o.reset();
  1534. QVERIFY(engine->evaluate("object.method_default(10)").strictlyEquals(QScriptValue(19)));
  1535. QCOMPARE(o.error(), false);
  1536. QCOMPARE(o.invoked(), 20);
  1537. QCOMPARE(o.actuals().count(), 2);
  1538. QCOMPARE(o.actuals().at(0), QVariant(10));
  1539. QCOMPARE(o.actuals().at(1), QVariant(19));
  1540. o.reset();
  1541. QVERIFY(engine->evaluate("object.method_default(10, 13)").strictlyEquals(QScriptValue(13)));
  1542. QCOMPARE(o.error(), false);
  1543. QCOMPARE(o.invoked(), 20);
  1544. QCOMPARE(o.actuals().count(), 2);
  1545. QCOMPARE(o.actuals().at(0), QVariant(10));
  1546. QCOMPARE(o.actuals().at(1), QVariant(13));
  1547. o.reset();
  1548. QCOMPARE(engine->evaluate("object.method_inherited(9)").isUndefined(), true);
  1549. QCOMPARE(o.error(), false);
  1550. QCOMPARE(o.invoked(), -3);
  1551. QCOMPARE(o.actuals().count(), 1);
  1552. QCOMPARE(o.actuals().at(0), QVariant(9));
  1553. o.reset();
  1554. QCOMPARE(engine->evaluate("object.method_QVariant(9)").isUndefined(), true);
  1555. QCOMPARE(o.error(), false);
  1556. QCOMPARE(o.invoked(), 21);
  1557. QCOMPARE(o.actuals().count(), 2);
  1558. QCOMPARE(o.actuals().at(0), QVariant(9));
  1559. QCOMPARE(o.actuals().at(1), QVariant());
  1560. o.reset();
  1561. QCOMPARE(engine->evaluate("object.method_QVariant(\"Hello\", \"World\")").isUndefined(), true);
  1562. QCOMPARE(o.error(), false);
  1563. QCOMPARE(o.invoked(), 21);
  1564. QCOMPARE(o.actuals().count(), 2);
  1565. QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
  1566. QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
  1567. }
  1568. // QTBUG-13047 (check that you can pass registered object types as args)
  1569. void tst_qdeclarativeecmascript::invokableObjectArg()
  1570. {
  1571. QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
  1572. QObject *o = component.create();
  1573. QVERIFY(o);
  1574. MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
  1575. QVERIFY(qmlobject);
  1576. QCOMPARE(qmlobject->myinvokableObject, qmlobject);
  1577. delete o;
  1578. }
  1579. // QTBUG-13047 (check that you can return registered object types from methods)
  1580. void tst_qdeclarativeecmascript::invokableObjectRet()
  1581. {
  1582. QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
  1583. QObject *o = component.create();
  1584. QVERIFY(o);
  1585. QCOMPARE(o->property("test").toBool(), true);
  1586. delete o;
  1587. }
  1588. // QTBUG-5675
  1589. void tst_qdeclarativeecmascript::listToVariant()
  1590. {
  1591. QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
  1592. MyQmlContainer container;
  1593. QDeclarativeContext context(engine.rootContext());
  1594. context.setContextObject(&container);
  1595. QObject *object = component.create(&context);
  1596. QVERIFY(object != 0);
  1597. QVariant v = object->property("test");
  1598. QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
  1599. QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
  1600. delete object;
  1601. }
  1602. // QTBUG-7957
  1603. void tst_qdeclarativeecmascript::multiEngineObject()
  1604. {
  1605. MyQmlObject obj;
  1606. obj.setStringProperty("Howdy planet");
  1607. QDeclarativeEngine e1;
  1608. e1.rootContext()->setContextProperty("thing", &obj);
  1609. QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
  1610. QDeclarativeEngine e2;
  1611. e2.rootContext()->setContextProperty("thing", &obj);
  1612. QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
  1613. QObject *o1 = c1.create();
  1614. QObject *o2 = c2.create();
  1615. QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
  1616. QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
  1617. delete o2;
  1618. delete o1;
  1619. }
  1620. // Test that references to QObjects are cleanup when the object is destroyed
  1621. void tst_qdeclarativeecmascript::deletedObject()
  1622. {
  1623. QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
  1624. QObject *object = component.create();
  1625. QCOMPARE(object->property("test1").toBool(), true);
  1626. QCOMPARE(object->property("test2").toBool(), true);
  1627. QCOMPARE(object->property("test3").toBool(), true);
  1628. QCOMPARE(object->property("test4").toBool(), true);
  1629. delete object;
  1630. }
  1631. void tst_qdeclarativeecmascript::attachedPropertyScope()
  1632. {
  1633. QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
  1634. QObject *object = component.create();
  1635. QVERIFY(object != 0);
  1636. MyQmlAttachedObject *attached =
  1637. qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
  1638. QVERIFY(attached != 0);
  1639. QCOMPARE(object->property("value2").toInt(), 0);
  1640. attached->emitMySignal();
  1641. QCOMPARE(object->property("value2").toInt(), 9);
  1642. delete object;
  1643. }
  1644. void tst_qdeclarativeecmascript::scriptConnect()
  1645. {
  1646. {
  1647. QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
  1648. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1649. QVERIFY(object != 0);
  1650. QCOMPARE(object->property("test").toBool(), false);
  1651. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1652. QCOMPARE(object->property("test").toBool(), true);
  1653. delete object;
  1654. }
  1655. {
  1656. QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
  1657. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1658. QVERIFY(object != 0);
  1659. QCOMPARE(object->property("test").toBool(), false);
  1660. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1661. QCOMPARE(object->property("test").toBool(), true);
  1662. delete object;
  1663. }
  1664. {
  1665. QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
  1666. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1667. QVERIFY(object != 0);
  1668. QCOMPARE(object->property("test").toBool(), false);
  1669. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1670. QCOMPARE(object->property("test").toBool(), true);
  1671. delete object;
  1672. }
  1673. {
  1674. QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
  1675. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1676. QVERIFY(object != 0);
  1677. QCOMPARE(object->methodCalled(), false);
  1678. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1679. QCOMPARE(object->methodCalled(), true);
  1680. delete object;
  1681. }
  1682. {
  1683. QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
  1684. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1685. QVERIFY(object != 0);
  1686. QCOMPARE(object->methodCalled(), false);
  1687. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1688. QCOMPARE(object->methodCalled(), true);
  1689. delete object;
  1690. }
  1691. {
  1692. QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
  1693. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1694. QVERIFY(object != 0);
  1695. QCOMPARE(object->property("test").toInt(), 0);
  1696. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1697. QCOMPARE(object->property("test").toInt(), 2);
  1698. delete object;
  1699. }
  1700. }
  1701. void tst_qdeclarativeecmascript::scriptDisconnect()
  1702. {
  1703. {
  1704. QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
  1705. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1706. QVERIFY(object != 0);
  1707. QCOMPARE(object->property("test").toInt(), 0);
  1708. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1709. QCOMPARE(object->property("test").toInt(), 1);
  1710. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1711. QCOMPARE(object->property("test").toInt(), 2);
  1712. emit object->basicSignal();
  1713. QCOMPARE(object->property("test").toInt(), 2);
  1714. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1715. QCOMPARE(object->property("test").toInt(), 2);
  1716. delete object;
  1717. }
  1718. {
  1719. QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
  1720. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1721. QVERIFY(object != 0);
  1722. QCOMPARE(object->property("test").toInt(), 0);
  1723. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1724. QCOMPARE(object->property("test").toInt(), 1);
  1725. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1726. QCOMPARE(object->property("test").toInt(), 2);
  1727. emit object->basicSignal();
  1728. QCOMPARE(object->property("test").toInt(), 2);
  1729. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1730. QCOMPARE(object->property("test").toInt(), 2);
  1731. delete object;
  1732. }
  1733. {
  1734. QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
  1735. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1736. QVERIFY(object != 0);
  1737. QCOMPARE(object->property("test").toInt(), 0);
  1738. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1739. QCOMPARE(object->property("test").toInt(), 1);
  1740. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1741. QCOMPARE(object->property("test").toInt(), 2);
  1742. emit object->basicSignal();
  1743. QCOMPARE(object->property("test").toInt(), 2);
  1744. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1745. QCOMPARE(object->property("test").toInt(), 3);
  1746. delete object;
  1747. }
  1748. {
  1749. QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
  1750. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1751. QVERIFY(object != 0);
  1752. QCOMPARE(object->property("test").toInt(), 0);
  1753. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1754. QCOMPARE(object->property("test").toInt(), 1);
  1755. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1756. QCOMPARE(object->property("test").toInt(), 2);
  1757. emit object->basicSignal();
  1758. QCOMPARE(object->property("test").toInt(), 2);
  1759. emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
  1760. QCOMPARE(object->property("test").toInt(), 3);
  1761. delete object;
  1762. }
  1763. }
  1764. class OwnershipObject : public QObject
  1765. {
  1766. Q_OBJECT
  1767. public:
  1768. OwnershipObject() { object = new QObject; }
  1769. QPointer<QObject> object;
  1770. public slots:
  1771. QObject *getObject() { return object; }
  1772. };
  1773. void tst_qdeclarativeecmascript::ownership()
  1774. {
  1775. OwnershipObject own;
  1776. QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
  1777. context->setContextObject(&own);
  1778. {
  1779. QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
  1780. QVERIFY(own.object != 0);
  1781. QObject *object = component.create(context);
  1782. QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
  1783. QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
  1784. QVERIFY(own.object == 0);
  1785. delete object;
  1786. }
  1787. own.object = new QObject(&own);
  1788. {
  1789. QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
  1790. QVERIFY(own.object != 0);
  1791. QObject *object = component.create(context);
  1792. QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
  1793. QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
  1794. QVERIFY(own.object != 0);
  1795. delete object;
  1796. }
  1797. }
  1798. class CppOwnershipReturnValue : public QObject
  1799. {
  1800. Q_OBJECT
  1801. public:
  1802. CppOwnershipReturnValue() : value(0) {}
  1803. ~CppOwnershipReturnValue() { delete value; }
  1804. Q_INVOKABLE QObject *create() {
  1805. value = new QObject;
  1806. QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
  1807. return value;
  1808. }
  1809. Q_INVOKABLE MyQmlObject *createQmlObject() {
  1810. MyQmlObject *rv = new MyQmlObject;
  1811. value = rv;
  1812. return rv;
  1813. }
  1814. QPointer<QObject> value;
  1815. };
  1816. // QTBUG-15695.
  1817. // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
  1818. void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
  1819. {
  1820. CppOwnershipReturnValue source;
  1821. {
  1822. QDeclarativeEngine engine;
  1823. engine.rootContext()->setContextProperty("source", &source);
  1824. QVERIFY(source.value == 0);
  1825. QDeclarativeComponent component(&engine);
  1826. component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
  1827. QObject *object = component.create();
  1828. QVERIFY(object != 0);
  1829. QVERIFY(source.value != 0);
  1830. delete object;
  1831. }
  1832. QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
  1833. QVERIFY(source.value != 0);
  1834. }
  1835. // QTBUG-15697
  1836. void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
  1837. {
  1838. CppOwnershipReturnValue source;
  1839. {
  1840. QDeclarativeEngine engine;
  1841. engine.rootContext()->setContextProperty("source", &source);
  1842. QVERIFY(source.value == 0);
  1843. QDeclarativeComponent component(&engine);
  1844. component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
  1845. QObject *object = component.create();
  1846. QVERIFY(object != 0);
  1847. QVERIFY(source.value != 0);
  1848. delete object;
  1849. }
  1850. QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
  1851. QVERIFY(source.value == 0);
  1852. }
  1853. class QListQObjectMethodsObject : public QObject
  1854. {
  1855. Q_OBJECT
  1856. public:
  1857. QListQObjectMethodsObject() {
  1858. m_objects.append(new MyQmlObject());
  1859. m_objects.append(new MyQmlObject());
  1860. }
  1861. ~QListQObjectMethodsObject() {
  1862. qDeleteAll(m_objects);
  1863. }
  1864. public slots:
  1865. QList<QObject *> getObjects() { return m_objects; }
  1866. private:
  1867. QList<QObject *> m_objects;
  1868. };
  1869. // Tests that returning a QList<QObject*> from a method works
  1870. void tst_qdeclarativeecmascript::qlistqobjectMethods()
  1871. {
  1872. QListQObjectMethodsObject obj;
  1873. QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
  1874. context->setContextObject(&obj);
  1875. QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
  1876. QObject *object = component.create(context);
  1877. QCOMPARE(object->property("test").toInt(), 2);
  1878. QCOMPARE(object->property("test2").toBool(), true);
  1879. delete object;
  1880. }
  1881. // QTBUG-9205
  1882. void tst_qdeclarativeecmascript::strictlyEquals()
  1883. {
  1884. QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
  1885. QObject *object = component.create();
  1886. QVERIFY(object != 0);
  1887. QCOMPARE(object->property("test1").toBool(), true);
  1888. QCOMPARE(object->property("test2").toBool(), true);
  1889. QCOMPARE(object->property("test3").toBool(), true);
  1890. QCOMPARE(object->property("test4").toBool(), true);
  1891. QCOMPARE(object->property("test5").toBool(), true);
  1892. QCOMPARE(object->property("test6").toBool(), true);
  1893. QCOMPARE(object->property("test7").toBool(), true);
  1894. QCOMPARE(object->property("test8").toBool(), true);
  1895. delete object;
  1896. }
  1897. void tst_qdeclarativeecmascript::compiled()
  1898. {
  1899. QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
  1900. QObject *object = component.create();
  1901. QVERIFY(object != 0);
  1902. QCOMPARE(object->property("test1").toReal(), qreal(15.7));
  1903. QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
  1904. QCOMPARE(object->property("test3").toBool(), true);
  1905. QCOMPARE(object->property("test4").toBool(), false);
  1906. QCOMPARE(object->property("test5").toBool(), false);
  1907. QCOMPARE(object->property("test6").toBool(), true);
  1908. QCOMPARE(object->property("test7").toInt(), 185);
  1909. QCOMPARE(object->property("test8").toInt(), 167);
  1910. QCOMPARE(object->property("test9").toBool(), true);
  1911. QCOMPARE(object->property("test10").toBool(), false);
  1912. QCOMPARE(object->property("test11").toBool(), false);
  1913. QCOMPARE(object->property("test12").toBool(), true);
  1914. QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
  1915. QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
  1916. QCOMPARE(object->property("test15").toBool(), false);
  1917. QCOMPARE(object->property("test16").toBool(), true);
  1918. QCOMPARE(object->property("test17").toInt(), 5);
  1919. QCOMPARE(object->property("test18").toReal(), qreal(176));
  1920. QCOMPARE(object->property("test19").toInt(), 7);
  1921. QCOMPARE(object->property("test20").toReal(), qreal(6.7));
  1922. QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
  1923. QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
  1924. QCOMPARE(object->property("test23").toBool(), true);
  1925. QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
  1926. QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
  1927. delete object;
  1928. }
  1929. // Test that numbers assigned in bindings as strings work consistently
  1930. void tst_qdeclarativeecmascript::numberAssignment()
  1931. {
  1932. QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
  1933. QObject *object = component.create();
  1934. QVERIFY(object != 0);
  1935. QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
  1936. QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
  1937. QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
  1938. QCOMPARE(object->property("test3"), QVariant((qreal)6));
  1939. QCOMPARE(object->property("test4"), QVariant((qreal)6));
  1940. QCOMPARE(object->property("test5"), QVariant((int)7));
  1941. QCOMPARE(object->property("test6"), QVariant((int)7));
  1942. QCOMPARE(object->property("test7"), QVariant((int)6));
  1943. QCOMPARE(object->property("test8"), QVariant((int)6));
  1944. QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
  1945. QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
  1946. QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
  1947. QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
  1948. delete object;
  1949. }
  1950. void tst_qdeclarativeecmascript::propertySplicing()
  1951. {
  1952. QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
  1953. QObject *object = component.create();
  1954. QVERIFY(object != 0);
  1955. QCOMPARE(object->property("test").toBool(), true);
  1956. delete object;
  1957. }
  1958. // QTBUG-16683
  1959. void tst_qdeclarativeecmascript::signalWithUnknownTypes()
  1960. {
  1961. QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
  1962. MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
  1963. QVERIFY(object != 0);
  1964. MyQmlObject::MyType type;
  1965. type.value = 0x8971123;
  1966. emit object->signalWithUnknownType(type);
  1967. MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
  1968. QCOMPARE(result.value, type.value);
  1969. delete object;
  1970. }
  1971. // Test that assigning a null object works
  1972. // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
  1973. void tst_qdeclarativeecmascript::nullObjectBinding()
  1974. {
  1975. QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
  1976. QObject *object = component.create();
  1977. QVERIFY(object != 0);
  1978. QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
  1979. delete object;
  1980. }
  1981. // Test that bindings don't evaluate once the engine has been destroyed
  1982. void tst_qdeclarativeecmascript::deletedEngine()
  1983. {
  1984. QDeclarativeEngine *engine = new QDeclarativeEngine;
  1985. QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
  1986. QObject *object = component.create();
  1987. QVERIFY(object != 0);
  1988. QCOMPARE(object->property("a").toInt(), 39);
  1989. object->setProperty("b", QVariant(9));
  1990. QCOMPARE(object->property("a").toInt(), 117);
  1991. delete engine;
  1992. QCOMPARE(object->property("a").toInt(), 117);
  1993. object->setProperty("b", QVariant(10));
  1994. QCOMPARE(object->property("a").toInt(), 117);
  1995. delete object;
  1996. }
  1997. // Test the crashing part of QTBUG-9705
  1998. void tst_qdeclarativeecmascript::libraryScriptAssert()
  1999. {
  2000. QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
  2001. QObject *object = component.create();
  2002. QVERIFY(object != 0);
  2003. delete object;
  2004. }
  2005. void tst_qdeclarativeecmascript::variantsAssignedUndefined()
  2006. {
  2007. QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
  2008. QObject *object = component.create();
  2009. QVERIFY(object != 0);
  2010. QCOMPARE(object->property("test1").toInt(), 10);
  2011. QCOMPARE(object->property("test2").toInt(), 11);
  2012. object->setProperty("runTest", true);
  2013. QCOMPARE(object->property("test1"), QVariant());
  2014. QCOMPARE(object->property("test2"), QVariant());
  2015. delete object;
  2016. }
  2017. void tst_qdeclarativeecmascript::qtbug_9792()
  2018. {
  2019. QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
  2020. QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
  2021. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
  2022. QVERIFY(object != 0);
  2023. QTest::ignoreMessage(QtDebugMsg, "Hello world!");
  2024. object->basicSignal();
  2025. delete context;
  2026. transientErrorsMsgCount = 0;
  2027. QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
  2028. object->basicSignal();
  2029. qInstallMsgHandler(old);
  2030. QCOMPARE(transientErrorsMsgCount, 0);
  2031. delete object;
  2032. }
  2033. // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
  2034. void tst_qdeclarativeecmascript::qtcreatorbug_1289()
  2035. {
  2036. QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
  2037. QObject *o = component.create();
  2038. QVERIFY(o != 0);
  2039. QObject *nested = qvariant_cast<QObject *>(o->property("object"));
  2040. QVERIFY(nested != 0);
  2041. QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
  2042. delete nested;
  2043. nested = qvariant_cast<QObject *>(o->property("object"));
  2044. QVERIFY(nested == 0);
  2045. // If the bug is present, the next line will crash
  2046. delete o;
  2047. }
  2048. // Test that we shut down without stupid warnings
  2049. void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
  2050. {
  2051. {
  2052. QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
  2053. QObject *o = component.create();
  2054. transientErrorsMsgCount = 0;
  2055. QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
  2056. delete o;
  2057. qInstallMsgHandler(old);
  2058. QCOMPARE(transientErrorsMsgCount, 0);
  2059. }
  2060. {
  2061. QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
  2062. QObject *o = component.create();
  2063. transientErrorsMsgCount = 0;
  2064. QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
  2065. delete o;
  2066. qInstallMsgHandler(old);
  2067. QCOMPARE(transientErrorsMsgCount, 0);
  2068. }
  2069. }
  2070. void tst_qdeclarativeecmascript::canAssignNullToQObject()
  2071. {
  2072. {
  2073. QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
  2074. MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
  2075. QVERIFY(o != 0);
  2076. QVERIFY(o->objectProperty() != 0);
  2077. o->setProperty("runTest", true);
  2078. QVERIFY(o->objectProperty() == 0);
  2079. delete o;
  2080. }
  2081. {
  2082. QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
  2083. MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
  2084. QVERIFY(o != 0);
  2085. QVERIFY(o->objectProperty() == 0);
  2086. delete o;
  2087. }
  2088. }
  2089. void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
  2090. {
  2091. QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
  2092. QString url = component.url().toString();
  2093. QString warning = url + ":4: Unable to assign a function to a property.";
  2094. QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
  2095. MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
  2096. QVERIFY(o != 0);
  2097. QVERIFY(!o->property("a").isValid());
  2098. delete o;
  2099. }
  2100. void tst_qdeclarativeecmascript::functionAssignment_fromJS()
  2101. {
  2102. QFETCH(QString, triggerProperty);
  2103. QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
  2104. QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
  2105. MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
  2106. QVERIFY(o != 0);
  2107. QVERIFY(!o->property("a").isValid());
  2108. o->setProperty("aNumber", QVariant(5));
  2109. o->setProperty(triggerProperty.toUtf8().constData(), true);
  2110. QCOMPARE(o->property("a"), QVariant(50));
  2111. o->setProperty("aNumber", QVariant(10));
  2112. QCOMPARE(o->property("a"), QVariant(100));
  2113. delete o;
  2114. }
  2115. void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
  2116. {
  2117. QTest::addColumn<QString>("triggerProperty");
  2118. QTest::newRow("assign to property") << "assignToProperty";
  2119. QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
  2120. QTest::newRow("assign to value type") << "assignToValueType";
  2121. QTest::newRow("use 'this'") << "assignWithThis";
  2122. QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
  2123. }
  2124. void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
  2125. {
  2126. QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
  2127. QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
  2128. MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
  2129. QVERIFY(o != 0);
  2130. QVERIFY(!o->property("a").isValid());
  2131. o->setProperty("assignFuncWithoutReturn", true);
  2132. QVERIFY(!o->property("a").isValid());
  2133. QString url = component.url().toString();
  2134. QString warning = url + ":63: Unable to assign QString to int";
  2135. QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
  2136. o->setProperty("assignWrongType", true);
  2137. warning = url + ":70: Unable to assign QString to int";
  2138. QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
  2139. o->setProperty("assignWrongTypeToValueType", true);
  2140. delete o;
  2141. }
  2142. void tst_qdeclarativeecmascript::eval()
  2143. {
  2144. QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
  2145. QObject *o = component.create();
  2146. QVERIFY(o != 0);
  2147. QCOMPARE(o->property("test1").toBool(), true);
  2148. QCOMPARE(o->property("test2").toBool(), true);
  2149. QCOMPARE(o->property("test3").toBool(), true);
  2150. QCOMPARE(o->property("test4").toBool(), true);
  2151. QCOMPARE(o->property("test5").toBool(), true);
  2152. delete o;
  2153. }
  2154. void tst_qdeclarativeecmascript::function()
  2155. {
  2156. QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
  2157. QObject *o = component.create();
  2158. QVERIFY(o != 0);
  2159. QCOMPARE(o->property("test1").toBool(), true);
  2160. QCOMPARE(o->property("test2").toBool(), true);
  2161. QCOMPARE(o->property("test3").toBool(), true);
  2162. delete o;
  2163. }
  2164. // Test the "Qt.include" method
  2165. void tst_qdeclarativeecmascript::include()
  2166. {
  2167. // Non-library relative include
  2168. {
  2169. QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
  2170. QObject *o = component.create();
  2171. QVERIFY(o != 0);
  2172. QCOMPARE(o->property("test0").toInt(), 99);
  2173. QCOMPARE(o->property("test1").toBool(), true);
  2174. QCOMPARE(o->property("test2").toBool(), true);
  2175. QCOMPARE(o->property("test2_1").toBool(), true);
  2176. QCOMPARE(o->property("test3").toBool(), true);
  2177. QCOMPARE(o->property("test3_1").toBool(), true);
  2178. delete o;
  2179. }
  2180. // Library relative include
  2181. {
  2182. QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
  2183. QObject *o = component.create();
  2184. QVERIFY(o != 0);
  2185. QCOMPARE(o->property("test0").toInt(), 99);
  2186. QCOMPARE(o->property("test1").toBool(), true);
  2187. QCOMPARE(o->property("test2").toBool(), true);
  2188. QCOMPARE(o->property("test2_1").toBool(), true);
  2189. QCOMPARE(o->property("test3").toBool(), true);
  2190. QCOMPARE(o->property("test3_1").toBool(), true);
  2191. delete o;
  2192. }
  2193. // Callback
  2194. {
  2195. QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
  2196. QObject *o = component.create();
  2197. QVERIFY(o != 0);
  2198. QCOMPARE(o->property("test1").toBool(), true);
  2199. QCOMPARE(o->property("test2").toBool(), true);
  2200. QCOMPARE(o->property("test3").toBool(), true);
  2201. QCOMPARE(o->property("test4").toBool(), true);
  2202. QCOMPARE(o->property("test5").toBool(), true);
  2203. QCOMPARE(o->property("test6").toBool(), true);
  2204. delete o;
  2205. }
  2206. // Including file with ".pragma library"
  2207. {
  2208. QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
  2209. QObject *o = component.create();
  2210. QVERIFY(o != 0);
  2211. QCOMPARE(o->property("test1").toInt(), 100);
  2212. delete o;
  2213. }
  2214. // Remote - success
  2215. {
  2216. TestHTTPServer server(8111);
  2217. QVERIFY(server.isValid());
  2218. server.serveDirectory(SRCDIR "/data");
  2219. QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
  2220. QObject *o = component.create();
  2221. QVERIFY(o != 0);
  2222. QTRY_VERIFY(o->property("done").toBool() == true);
  2223. QTRY_VERIFY(o->property("done2").toBool() == true);
  2224. QCOMPARE(o->property("test1").toBool(), true);
  2225. QCOMPARE(o->property("test2").toBool(), true);
  2226. QCOMPARE(o->property("test3").toBool(), true);
  2227. QCOMPARE(o->property("test4").toBool(), true);
  2228. QCOMPARE(o->property("test5").toBool(), true);
  2229. QCOMPARE(o->property("test6").toBool(), true);
  2230. QCOMPARE(o->property("test7").toBool(), true);
  2231. QCOMPARE(o->property("test8").toBool(), true);
  2232. QCOMPARE(o->property("test9").toBool(), true);
  2233. QCOMPARE(o->property("test10").toBool(), true);
  2234. delete o;
  2235. }
  2236. // Remote - error
  2237. {
  2238. TestHTTPServer server(8111);
  2239. QVERIFY(server.isValid());
  2240. server.serveDirectory(SRCDIR "/data");
  2241. QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
  2242. QObject *o = component.create();
  2243. QVERIFY(o != 0);
  2244. QTRY_VERIFY(o->property("done").toBool() == true);
  2245. QCOMPARE(o->property("test1").toBool(), true);
  2246. QCOMPARE(o->property("test2").toBool(), true);
  2247. QCOMPARE(o->property("test3").toBool(), true);
  2248. delete o;
  2249. }
  2250. }
  2251. void tst_qdeclarativeecmascript::qtbug_10696()
  2252. {
  2253. QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
  2254. QObject *o = component.create();
  2255. QVERIFY(o != 0);
  2256. delete o;
  2257. }
  2258. void tst_qdeclarativeecmascript::qtbug_11606()
  2259. {
  2260. QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
  2261. QObject *o = component.create();
  2262. QVERIFY(o != 0);
  2263. QCOMPARE(o->property("test").toBool(), true);
  2264. delete o;
  2265. }
  2266. void tst_qdeclarativeecmascript::qtbug_11600()
  2267. {
  2268. QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
  2269. QObject *o = component.create();
  2270. QVERIFY(o != 0);
  2271. QCOMPARE(o->property("test").toBool(), true);
  2272. delete o;
  2273. }
  2274. // Reading and writing non-scriptable properties should fail
  2275. void tst_qdeclarativeecmascript::nonscriptable()
  2276. {
  2277. QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
  2278. QObject *o = component.create();
  2279. QVERIFY(o != 0);
  2280. QCOMPARE(o->property("readOk").toBool(), true);
  2281. QCOMPARE(o->property("writeOk").toBool(), true);
  2282. delete o;
  2283. }
  2284. // deleteLater() should not be callable from QML
  2285. void tst_qdeclarativeecmascript::deleteLater()
  2286. {
  2287. QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
  2288. QObject *o = component.create();
  2289. QVERIFY(o != 0);
  2290. QCOMPARE(o->property("test").toBool(), true);
  2291. delete o;
  2292. }
  2293. void tst_qdeclarativeecmascript::in()
  2294. {
  2295. QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
  2296. QObject *o = component.create();
  2297. QVERIFY(o != 0);
  2298. QCOMPARE(o->property("test1").toBool(), true);
  2299. QCOMPARE(o->property("test2").toBool(), true);
  2300. delete o;
  2301. }
  2302. void tst_qdeclarativeecmascript::sharedAttachedObject()
  2303. {
  2304. QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
  2305. QObject *o = component.create();
  2306. QVERIFY(o != 0);
  2307. QCOMPARE(o->property("test1").toBool(), true);
  2308. QCOMPARE(o->property("test2").toBool(), true);
  2309. delete o;
  2310. }
  2311. // QTBUG-13999
  2312. void tst_qdeclarativeecmascript::objectName()
  2313. {
  2314. QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
  2315. QObject *o = component.create();
  2316. QVERIFY(o != 0);
  2317. QCOMPARE(o->property("test1").toString(), QString("hello"));
  2318. QCOMPARE(o->property("test2").toString(), QString("ell"));
  2319. o->setObjectName("world");
  2320. QCOMPARE(o->property("test1").toString(), QString("world"));
  2321. QCOMPARE(o->property("test2").toString(), QString("orl"));
  2322. delete o;
  2323. }
  2324. void tst_qdeclarativeecmascript::writeRemovesBinding()
  2325. {
  2326. QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
  2327. QObject *o = component.create();
  2328. QVERIFY(o != 0);
  2329. QCOMPARE(o->property("test").toBool(), true);
  2330. delete o;
  2331. }
  2332. // Test bindings assigned to alias properties actually assign to the alias' target
  2333. void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
  2334. {
  2335. QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
  2336. QObject *o = component.create();
  2337. QVERIFY(o != 0);
  2338. QCOMPARE(o->property("test").toBool(), true);
  2339. delete o;
  2340. }
  2341. // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
  2342. void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
  2343. {
  2344. {
  2345. QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
  2346. QObject *o = component.create();
  2347. QVERIFY(o != 0);
  2348. QCOMPARE(o->property("test").toBool(), true);
  2349. delete o;
  2350. }
  2351. {
  2352. QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
  2353. QObject *o = component.create();
  2354. QVERIFY(o != 0);
  2355. QCOMPARE(o->property("test").toBool(), true);
  2356. delete o;
  2357. }
  2358. {
  2359. QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
  2360. QObject *o = component.create();
  2361. QVERIFY(o != 0);
  2362. QCOMPARE(o->property("test").toBool(), true);
  2363. delete o;
  2364. }
  2365. }
  2366. // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
  2367. void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
  2368. {
  2369. {
  2370. QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
  2371. QObject *o = component.create();
  2372. QVERIFY(o != 0);
  2373. QCOMPARE(o->property("test").toBool(), true);
  2374. delete o;
  2375. }
  2376. {
  2377. QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
  2378. QObject *o = component.create();
  2379. QVERIFY(o != 0);
  2380. QCOMPARE(o->property("test").toBool(), true);
  2381. delete o;
  2382. }
  2383. {
  2384. QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
  2385. QObject *o = component.create();
  2386. QVERIFY(o != 0);
  2387. QCOMPARE(o->property("test").toBool(), true);
  2388. delete o;
  2389. }
  2390. }
  2391. void tst_qdeclarativeecmascript::revisionErrors()
  2392. {
  2393. {
  2394. QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
  2395. QString url = component.url().toString();
  2396. QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
  2397. QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
  2398. QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
  2399. QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
  2400. QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
  2401. QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
  2402. MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
  2403. QVERIFY(object != 0);
  2404. }
  2405. {
  2406. QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
  2407. QString url = component.url().toString();
  2408. // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
  2409. // method2, prop2 from MyRevisionedClass not available
  2410. // method4, prop4 from MyRevisionedSubclass not available
  2411. QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
  2412. QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
  2413. QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
  2414. QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
  2415. QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
  2416. QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
  2417. QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
  2418. QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
  2419. QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
  2420. QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
  2421. MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
  2422. QVERIFY(object != 0);
  2423. }
  2424. {
  2425. QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
  2426. QString url = component.url().toString();
  2427. // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
  2428. // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
  2429. QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
  2430. QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
  2431. QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
  2432. QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
  2433. QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
  2434. QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
  2435. MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
  2436. QVERIFY(object != 0);
  2437. }
  2438. }
  2439. void tst_qdeclarativeecmascript::revision()
  2440. {
  2441. {
  2442. QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
  2443. QString url = component.url().toString();
  2444. MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
  2445. QVERIFY(object != 0);
  2446. }
  2447. {
  2448. QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
  2449. QString url = component.url().toString();
  2450. MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
  2451. QVERIFY(object != 0);
  2452. }
  2453. {
  2454. QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
  2455. QString url = component.url().toString();
  2456. MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
  2457. QVERIFY(object != 0);
  2458. }
  2459. // Test that non-root classes can resolve revisioned methods
  2460. {
  2461. QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
  2462. QObject *object = component.create();
  2463. QVERIFY(object != 0);
  2464. QCOMPARE(object->property("test").toReal(), 11.);
  2465. delete object;
  2466. }
  2467. }
  2468. // Test for QScriptDeclarativeClass::pushCleanContext()
  2469. void tst_qdeclarativeecmascript::pushCleanContext()
  2470. {
  2471. QScriptEngine engine;
  2472. engine.globalObject().setProperty("a", 6);
  2473. QCOMPARE(engine.evaluate("a").toInt32(), 6);
  2474. // First confirm pushContext() behaves as we expect
  2475. QScriptValue object = engine.newObject();
  2476. object.setProperty("a", 15);
  2477. QScriptContext *context1 = engine.pushContext();
  2478. context1->pushScope(object);
  2479. QCOMPARE(engine.evaluate("a").toInt32(), 15);
  2480. QScriptContext *context2 = engine.pushContext();
  2481. Q_UNUSED(context2);
  2482. QCOMPARE(engine.evaluate("a").toInt32(), 15);
  2483. QScriptValue func1 = engine.evaluate("(function() { return a; })");
  2484. // Now check that pushCleanContext() works
  2485. QScriptDeclarativeClass::pushCleanContext(&engine);
  2486. QCOMPARE(engine.evaluate("a").toInt32(), 6);
  2487. QScriptValue func2 = engine.evaluate("(function() { return a; })");
  2488. engine.popContext();
  2489. QCOMPARE(engine.evaluate("a").toInt32(), 15);
  2490. engine.popContext();
  2491. QCOMPARE(engine.evaluate("a").toInt32(), 15);
  2492. engine.popContext();
  2493. QCOMPARE(engine.evaluate("a").toInt32(), 6);
  2494. // Check that function objects created in these contexts work
  2495. QCOMPARE(func1.call().toInt32(), 15);
  2496. QCOMPARE(func2.call().toInt32(), 6);
  2497. }
  2498. void tst_qdeclarativeecmascript::realToInt()
  2499. {
  2500. QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
  2501. MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
  2502. QVERIFY(object != 0);
  2503. QMetaObject::invokeMethod(object, "test1");
  2504. QCOMPARE(object->value(), int(4));
  2505. QMetaObject::invokeMethod(object, "test2");
  2506. QCOMPARE(object->value(), int(8));
  2507. }
  2508. void tst_qdeclarativeecmascript::qtbug_20648()
  2509. {
  2510. QDeclarativeComponent component(&engine, TEST_FILE("qtbug_20648.qml"));
  2511. QObject *o = component.create();
  2512. QVERIFY(o != 0);
  2513. QCOMPARE(o->property("test").toInt(), 100);
  2514. delete o;
  2515. }
  2516. QTEST_MAIN(tst_qdeclarativeecmascript)
  2517. #include "tst_qdeclarativeecmascript.moc"