1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
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"
59 // In Symbian OS test data is located in applications private dir
64 This test covers evaluation of ECMAScript expressions and bindings from within
65 QML. This does not include static QML language issues.
67 Static QML language issues are covered in qmllanguage
69 inline QUrl TEST_FILE(const QString &filename)
71 QFileInfo fileInfo(__FILE__);
72 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
75 inline QUrl TEST_FILE(const char *filename)
77 return TEST_FILE(QLatin1String(filename));
80 class tst_qdeclarativeecmascript : public QObject
84 tst_qdeclarativeecmascript() {}
88 void assignBasicTypes();
89 void idShortcutInvalidates();
90 void boolPropertiesEvaluateAsBool();
92 void signalAssignment();
94 void basicExpressions();
95 void basicExpressions_data();
96 void arrayExpressions();
97 void contextPropertiesTriggerReeval();
98 void objectPropertiesTriggerReeval();
99 void deferredProperties();
100 void deferredPropertiesErrors();
101 void extensionObjects();
102 void overrideExtensionProperties();
103 void attachedProperties();
105 void valueTypeFunctions();
106 void constantsOverrideBindings();
107 void outerBindingOverridesInnerBinding();
108 void aliasPropertyAndBinding();
109 void nonExistentAttachedObject();
111 void signalParameterTypes();
112 void objectsCompareAsEqual();
113 void dynamicCreation_data();
114 void dynamicCreation();
115 void dynamicDestruction();
116 void objectToString();
117 void selfDeletingBinding();
118 void extendedObjectPropertyLookup();
120 void functionErrors();
121 void propertyAssignmentErrors();
122 void signalTriggeredBindings();
123 void listProperties();
124 void exceptionClearsOnReeval();
125 void exceptionSlotProducesWarning();
126 void exceptionBindingProducesWarning();
127 void transientErrors();
128 void shutdownErrors();
129 void compositePropertyType();
131 void undefinedResetsProperty();
132 void listToVariant();
133 void multiEngineObject();
134 void deletedObject();
135 void attachedPropertyScope();
136 void scriptConnect();
137 void scriptDisconnect();
139 void cppOwnershipReturnValue();
140 void ownershipCustomReturnValue();
141 void qlistqobjectMethods();
142 void strictlyEquals();
144 void numberAssignment();
145 void propertySplicing();
146 void signalWithUnknownTypes();
148 void importScripts();
149 void scarceResources();
153 void dynamicCreationCrash();
155 void nullObjectBinding();
156 void deletedEngine();
157 void libraryScriptAssert();
158 void variantsAssignedUndefined();
160 void qtcreatorbug_1289();
161 void noSpuriousWarningsAtShutdown();
162 void canAssignNullToQObject();
163 void functionAssignment_fromBinding();
164 void functionAssignment_fromJS();
165 void functionAssignment_fromJS_data();
166 void functionAssignmentfromJS_invalid();
172 void nonscriptable();
175 void sharedAttachedObject();
177 void writeRemovesBinding();
178 void aliasBindingsAssignCorrectly();
179 void aliasBindingsOverrideTarget();
180 void aliasWritesOverrideBindings();
181 void pushCleanContext();
186 void callQtInvokables();
187 void invokableObjectArg();
188 void invokableObjectRet();
190 void revisionErrors();
193 QDeclarativeEngine engine;
196 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
198 void tst_qdeclarativeecmascript::assignBasicTypes()
201 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
202 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
203 QVERIFY(object != 0);
204 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
205 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
206 QCOMPARE(object->stringProperty(), QString("Hello World!"));
207 QCOMPARE(object->uintProperty(), uint(10));
208 QCOMPARE(object->intProperty(), -19);
209 QCOMPARE((float)object->realProperty(), float(23.2));
210 QCOMPARE((float)object->doubleProperty(), float(-19.75));
211 QCOMPARE((float)object->floatProperty(), float(8.5));
212 QCOMPARE(object->colorProperty(), QColor("red"));
213 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
214 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
215 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
216 QCOMPARE(object->pointProperty(), QPoint(99,13));
217 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
218 QCOMPARE(object->sizeProperty(), QSize(99, 13));
219 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
220 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
221 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
222 QCOMPARE(object->boolProperty(), true);
223 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
224 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
225 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
229 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
230 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
231 QVERIFY(object != 0);
232 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
233 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
234 QCOMPARE(object->stringProperty(), QString("Hello World!"));
235 QCOMPARE(object->uintProperty(), uint(10));
236 QCOMPARE(object->intProperty(), -19);
237 QCOMPARE((float)object->realProperty(), float(23.2));
238 QCOMPARE((float)object->doubleProperty(), float(-19.75));
239 QCOMPARE((float)object->floatProperty(), float(8.5));
240 QCOMPARE(object->colorProperty(), QColor("red"));
241 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
242 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
243 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
244 QCOMPARE(object->pointProperty(), QPoint(99,13));
245 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
246 QCOMPARE(object->sizeProperty(), QSize(99, 13));
247 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
248 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
249 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
250 QCOMPARE(object->boolProperty(), true);
251 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
252 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
253 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
258 void tst_qdeclarativeecmascript::idShortcutInvalidates()
261 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
262 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
263 QVERIFY(object != 0);
264 QVERIFY(object->objectProperty() != 0);
265 delete object->objectProperty();
266 QVERIFY(object->objectProperty() == 0);
271 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
272 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
273 QVERIFY(object != 0);
274 QVERIFY(object->objectProperty() != 0);
275 delete object->objectProperty();
276 QVERIFY(object->objectProperty() == 0);
281 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
284 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
285 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
286 QVERIFY(object != 0);
287 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
291 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
292 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
293 QVERIFY(object != 0);
294 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
299 void tst_qdeclarativeecmascript::signalAssignment()
302 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
303 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
304 QVERIFY(object != 0);
305 QCOMPARE(object->string(), QString());
306 emit object->basicSignal();
307 QCOMPARE(object->string(), QString("pass"));
312 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
313 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
314 QVERIFY(object != 0);
315 QCOMPARE(object->string(), QString());
316 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
317 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
322 void tst_qdeclarativeecmascript::methods()
325 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
326 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
327 QVERIFY(object != 0);
328 QCOMPARE(object->methodCalled(), false);
329 QCOMPARE(object->methodIntCalled(), false);
330 emit object->basicSignal();
331 QCOMPARE(object->methodCalled(), true);
332 QCOMPARE(object->methodIntCalled(), false);
337 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
338 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
339 QVERIFY(object != 0);
340 QCOMPARE(object->methodCalled(), false);
341 QCOMPARE(object->methodIntCalled(), false);
342 emit object->basicSignal();
343 QCOMPARE(object->methodCalled(), false);
344 QCOMPARE(object->methodIntCalled(), true);
349 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
350 QObject *object = component.create();
351 QVERIFY(object != 0);
352 QCOMPARE(object->property("test").toInt(), 19);
357 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
358 QObject *object = component.create();
359 QVERIFY(object != 0);
360 QCOMPARE(object->property("test").toInt(), 19);
361 QCOMPARE(object->property("test2").toInt(), 17);
362 QCOMPARE(object->property("test3").toInt(), 16);
367 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
368 QObject *object = component.create();
369 QVERIFY(object != 0);
370 QCOMPARE(object->property("test").toInt(), 9);
375 void tst_qdeclarativeecmascript::bindingLoop()
377 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
378 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
379 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
380 QObject *object = component.create();
381 QVERIFY(object != 0);
385 void tst_qdeclarativeecmascript::basicExpressions_data()
387 QTest::addColumn<QString>("expression");
388 QTest::addColumn<QVariant>("result");
389 QTest::addColumn<bool>("nest");
391 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
392 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
393 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
394 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
395 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
396 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
397 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
398 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
399 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
400 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
401 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
402 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
403 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
404 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
405 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
406 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
407 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
408 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
409 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
412 void tst_qdeclarativeecmascript::basicExpressions()
414 QFETCH(QString, expression);
415 QFETCH(QVariant, result);
421 MyDefaultObject1 default1;
422 MyDefaultObject3 default3;
423 object1.setStringProperty("Object1");
424 object2.setStringProperty("Object2");
425 object3.setStringProperty("Object3");
427 QDeclarativeContext context(engine.rootContext());
428 QDeclarativeContext nestedContext(&context);
430 context.setContextObject(&default1);
431 context.setContextProperty("a", QVariant(1944));
432 context.setContextProperty("b", QVariant("Milk"));
433 context.setContextProperty("object", &object1);
434 context.setContextProperty("objectOverride", &object2);
435 nestedContext.setContextObject(&default3);
436 nestedContext.setContextProperty("b", QVariant("Cow"));
437 nestedContext.setContextProperty("objectOverride", &object3);
438 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
440 MyExpression expr(nest?&nestedContext:&context, expression);
441 QCOMPARE(expr.evaluate(), result);
444 void tst_qdeclarativeecmascript::arrayExpressions()
450 QDeclarativeContext context(engine.rootContext());
451 context.setContextProperty("a", &obj1);
452 context.setContextProperty("b", &obj2);
453 context.setContextProperty("c", &obj3);
455 MyExpression expr(&context, "[a, b, c, 10]");
456 QVariant result = expr.evaluate();
457 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
458 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
459 QCOMPARE(list.count(), 4);
460 QCOMPARE(list.at(0), &obj1);
461 QCOMPARE(list.at(1), &obj2);
462 QCOMPARE(list.at(2), &obj3);
463 QCOMPARE(list.at(3), (QObject *)0);
466 // Tests that modifying a context property will reevaluate expressions
467 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
469 QDeclarativeContext context(engine.rootContext());
472 MyQmlObject *object3 = new MyQmlObject;
474 object1.setStringProperty("Hello");
475 object2.setStringProperty("World");
477 context.setContextProperty("testProp", QVariant(1));
478 context.setContextProperty("testObj", &object1);
479 context.setContextProperty("testObj2", object3);
482 MyExpression expr(&context, "testProp + 1");
483 QCOMPARE(expr.changed, false);
484 QCOMPARE(expr.evaluate(), QVariant(2));
486 context.setContextProperty("testProp", QVariant(2));
487 QCOMPARE(expr.changed, true);
488 QCOMPARE(expr.evaluate(), QVariant(3));
492 MyExpression expr(&context, "testProp + testProp + testProp");
493 QCOMPARE(expr.changed, false);
494 QCOMPARE(expr.evaluate(), QVariant(6));
496 context.setContextProperty("testProp", QVariant(4));
497 QCOMPARE(expr.changed, true);
498 QCOMPARE(expr.evaluate(), QVariant(12));
502 MyExpression expr(&context, "testObj.stringProperty");
503 QCOMPARE(expr.changed, false);
504 QCOMPARE(expr.evaluate(), QVariant("Hello"));
506 context.setContextProperty("testObj", &object2);
507 QCOMPARE(expr.changed, true);
508 QCOMPARE(expr.evaluate(), QVariant("World"));
512 MyExpression expr(&context, "testObj.stringProperty /**/");
513 QCOMPARE(expr.changed, false);
514 QCOMPARE(expr.evaluate(), QVariant("World"));
516 context.setContextProperty("testObj", &object1);
517 QCOMPARE(expr.changed, true);
518 QCOMPARE(expr.evaluate(), QVariant("Hello"));
522 MyExpression expr(&context, "testObj2");
523 QCOMPARE(expr.changed, false);
524 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
530 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
532 QDeclarativeContext context(engine.rootContext());
536 context.setContextProperty("testObj", &object1);
538 object1.setStringProperty(QLatin1String("Hello"));
539 object2.setStringProperty(QLatin1String("Dog"));
540 object3.setStringProperty(QLatin1String("Cat"));
543 MyExpression expr(&context, "testObj.stringProperty");
544 QCOMPARE(expr.changed, false);
545 QCOMPARE(expr.evaluate(), QVariant("Hello"));
547 object1.setStringProperty(QLatin1String("World"));
548 QCOMPARE(expr.changed, true);
549 QCOMPARE(expr.evaluate(), QVariant("World"));
553 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
554 QCOMPARE(expr.changed, false);
555 QCOMPARE(expr.evaluate(), QVariant());
557 object1.setObjectProperty(&object2);
558 QCOMPARE(expr.changed, true);
559 expr.changed = false;
560 QCOMPARE(expr.evaluate(), QVariant("Dog"));
562 object1.setObjectProperty(&object3);
563 QCOMPARE(expr.changed, true);
564 expr.changed = false;
565 QCOMPARE(expr.evaluate(), QVariant("Cat"));
567 object1.setObjectProperty(0);
568 QCOMPARE(expr.changed, true);
569 expr.changed = false;
570 QCOMPARE(expr.evaluate(), QVariant());
572 object1.setObjectProperty(&object3);
573 QCOMPARE(expr.changed, true);
574 expr.changed = false;
575 QCOMPARE(expr.evaluate(), QVariant("Cat"));
577 object3.setStringProperty("Donkey");
578 QCOMPARE(expr.changed, true);
579 expr.changed = false;
580 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
584 void tst_qdeclarativeecmascript::deferredProperties()
586 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
587 MyDeferredObject *object =
588 qobject_cast<MyDeferredObject *>(component.create());
589 QVERIFY(object != 0);
590 QCOMPARE(object->value(), 0);
591 QVERIFY(object->objectProperty() == 0);
592 QVERIFY(object->objectProperty2() != 0);
593 qmlExecuteDeferred(object);
594 QCOMPARE(object->value(), 10);
595 QVERIFY(object->objectProperty() != 0);
596 MyQmlObject *qmlObject =
597 qobject_cast<MyQmlObject *>(object->objectProperty());
598 QVERIFY(qmlObject != 0);
599 QCOMPARE(qmlObject->value(), 10);
600 object->setValue(19);
601 QCOMPARE(qmlObject->value(), 19);
606 // Check errors on deferred properties are correctly emitted
607 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
609 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
610 MyDeferredObject *object =
611 qobject_cast<MyDeferredObject *>(component.create());
612 QVERIFY(object != 0);
613 QCOMPARE(object->value(), 0);
614 QVERIFY(object->objectProperty() == 0);
615 QVERIFY(object->objectProperty2() == 0);
617 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
618 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
620 qmlExecuteDeferred(object);
625 void tst_qdeclarativeecmascript::extensionObjects()
627 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
628 MyExtendedObject *object =
629 qobject_cast<MyExtendedObject *>(component.create());
630 QVERIFY(object != 0);
631 QCOMPARE(object->baseProperty(), 13);
632 QCOMPARE(object->coreProperty(), 9);
633 object->setProperty("extendedProperty", QVariant(11));
634 object->setProperty("baseExtendedProperty", QVariant(92));
635 QCOMPARE(object->coreProperty(), 11);
636 QCOMPARE(object->baseProperty(), 92);
638 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
640 QCOMPARE(nested->baseProperty(), 13);
641 QCOMPARE(nested->coreProperty(), 9);
642 nested->setProperty("extendedProperty", QVariant(11));
643 nested->setProperty("baseExtendedProperty", QVariant(92));
644 QCOMPARE(nested->coreProperty(), 11);
645 QCOMPARE(nested->baseProperty(), 92);
650 void tst_qdeclarativeecmascript::overrideExtensionProperties()
652 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
653 OverrideDefaultPropertyObject *object =
654 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
655 QVERIFY(object != 0);
656 QVERIFY(object->secondProperty() != 0);
657 QVERIFY(object->firstProperty() == 0);
662 void tst_qdeclarativeecmascript::attachedProperties()
665 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
666 QObject *object = component.create();
667 QVERIFY(object != 0);
668 QCOMPARE(object->property("a").toInt(), 19);
669 QCOMPARE(object->property("b").toInt(), 19);
670 QCOMPARE(object->property("c").toInt(), 19);
671 QCOMPARE(object->property("d").toInt(), 19);
676 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
677 QObject *object = component.create();
678 QVERIFY(object != 0);
679 QCOMPARE(object->property("a").toInt(), 26);
680 QCOMPARE(object->property("b").toInt(), 26);
681 QCOMPARE(object->property("c").toInt(), 26);
682 QCOMPARE(object->property("d").toInt(), 26);
686 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
687 QObject *object = component.create();
688 QVERIFY(object != 0);
690 QMetaObject::invokeMethod(object, "writeValue2");
692 MyQmlAttachedObject *attached =
693 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
694 QVERIFY(attached != 0);
696 QCOMPARE(attached->value2(), 9);
701 void tst_qdeclarativeecmascript::enums()
705 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
706 QObject *object = component.create();
707 QVERIFY(object != 0);
709 QCOMPARE(object->property("a").toInt(), 0);
710 QCOMPARE(object->property("b").toInt(), 1);
711 QCOMPARE(object->property("c").toInt(), 2);
712 QCOMPARE(object->property("d").toInt(), 3);
713 QCOMPARE(object->property("e").toInt(), 0);
714 QCOMPARE(object->property("f").toInt(), 1);
715 QCOMPARE(object->property("g").toInt(), 2);
716 QCOMPARE(object->property("h").toInt(), 3);
717 QCOMPARE(object->property("i").toInt(), 19);
718 QCOMPARE(object->property("j").toInt(), 19);
722 // Non-existent enums
724 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
726 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
727 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
728 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
729 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
731 QObject *object = component.create();
732 QVERIFY(object != 0);
733 QCOMPARE(object->property("a").toInt(), 0);
734 QCOMPARE(object->property("b").toInt(), 0);
740 void tst_qdeclarativeecmascript::valueTypeFunctions()
742 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
743 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
745 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
746 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
752 Tests that writing a constant to a property with a binding on it disables the
755 void tst_qdeclarativeecmascript::constantsOverrideBindings()
759 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
760 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
761 QVERIFY(object != 0);
763 QCOMPARE(object->property("c2").toInt(), 0);
764 object->setProperty("c1", QVariant(9));
765 QCOMPARE(object->property("c2").toInt(), 9);
767 emit object->basicSignal();
769 QCOMPARE(object->property("c2").toInt(), 13);
770 object->setProperty("c1", QVariant(8));
771 QCOMPARE(object->property("c2").toInt(), 13);
776 // During construction
778 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
779 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
780 QVERIFY(object != 0);
782 QCOMPARE(object->property("c1").toInt(), 0);
783 QCOMPARE(object->property("c2").toInt(), 10);
784 object->setProperty("c1", QVariant(9));
785 QCOMPARE(object->property("c1").toInt(), 9);
786 QCOMPARE(object->property("c2").toInt(), 10);
794 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
795 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
796 QVERIFY(object != 0);
798 QCOMPARE(object->property("c2").toInt(), 0);
799 object->setProperty("c1", QVariant(9));
800 QCOMPARE(object->property("c2").toInt(), 9);
802 object->setProperty("c2", QVariant(13));
803 QCOMPARE(object->property("c2").toInt(), 13);
804 object->setProperty("c1", QVariant(7));
805 QCOMPARE(object->property("c1").toInt(), 7);
806 QCOMPARE(object->property("c2").toInt(), 13);
814 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
815 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
816 QVERIFY(object != 0);
818 QCOMPARE(object->property("c1").toInt(), 0);
819 QCOMPARE(object->property("c3").toInt(), 10);
820 object->setProperty("c1", QVariant(9));
821 QCOMPARE(object->property("c1").toInt(), 9);
822 QCOMPARE(object->property("c3").toInt(), 10);
829 Tests that assigning a binding to a property that already has a binding causes
830 the original binding to be disabled.
832 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
834 QDeclarativeComponent component(&engine,
835 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
836 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
837 QVERIFY(object != 0);
839 QCOMPARE(object->property("c1").toInt(), 0);
840 QCOMPARE(object->property("c2").toInt(), 0);
841 QCOMPARE(object->property("c3").toInt(), 0);
843 object->setProperty("c1", QVariant(9));
844 QCOMPARE(object->property("c1").toInt(), 9);
845 QCOMPARE(object->property("c2").toInt(), 0);
846 QCOMPARE(object->property("c3").toInt(), 0);
848 object->setProperty("c3", QVariant(8));
849 QCOMPARE(object->property("c1").toInt(), 9);
850 QCOMPARE(object->property("c2").toInt(), 8);
851 QCOMPARE(object->property("c3").toInt(), 8);
857 Access a non-existent attached object.
859 Tests for a regression where this used to crash.
861 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
863 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
865 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
866 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
868 QObject *object = component.create();
869 QVERIFY(object != 0);
874 void tst_qdeclarativeecmascript::scope()
877 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
878 QObject *object = component.create();
879 QVERIFY(object != 0);
881 QCOMPARE(object->property("test1").toInt(), 1);
882 QCOMPARE(object->property("test2").toInt(), 2);
883 QCOMPARE(object->property("test3").toString(), QString("1Test"));
884 QCOMPARE(object->property("test4").toString(), QString("2Test"));
885 QCOMPARE(object->property("test5").toInt(), 1);
886 QCOMPARE(object->property("test6").toInt(), 1);
887 QCOMPARE(object->property("test7").toInt(), 2);
888 QCOMPARE(object->property("test8").toInt(), 2);
889 QCOMPARE(object->property("test9").toInt(), 1);
890 QCOMPARE(object->property("test10").toInt(), 3);
896 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
897 QObject *object = component.create();
898 QVERIFY(object != 0);
900 QCOMPARE(object->property("test1").toInt(), 19);
901 QCOMPARE(object->property("test2").toInt(), 19);
902 QCOMPARE(object->property("test3").toInt(), 14);
903 QCOMPARE(object->property("test4").toInt(), 14);
904 QCOMPARE(object->property("test5").toInt(), 24);
905 QCOMPARE(object->property("test6").toInt(), 24);
911 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
912 QObject *object = component.create();
913 QVERIFY(object != 0);
915 QCOMPARE(object->property("test1").toBool(), true);
916 QCOMPARE(object->property("test2").toBool(), true);
917 QCOMPARE(object->property("test3").toBool(), true);
922 // Signal argument scope
924 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
925 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
926 QVERIFY(object != 0);
928 QCOMPARE(object->property("test").toInt(), 0);
929 QCOMPARE(object->property("test2").toString(), QString());
931 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
933 QCOMPARE(object->property("test").toInt(), 13);
934 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
940 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
941 QObject *object = component.create();
942 QVERIFY(object != 0);
944 QCOMPARE(object->property("test1").toBool(), true);
945 QCOMPARE(object->property("test2").toBool(), true);
951 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
952 QObject *object = component.create();
953 QVERIFY(object != 0);
955 QCOMPARE(object->property("test").toBool(), true);
962 Tests that "any" type passes through a synthesized signal parameter. This
963 is essentially a test of QDeclarativeMetaType::copy()
965 void tst_qdeclarativeecmascript::signalParameterTypes()
967 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
968 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
969 QVERIFY(object != 0);
971 emit object->basicSignal();
973 QCOMPARE(object->property("intProperty").toInt(), 10);
974 QCOMPARE(object->property("realProperty").toReal(), 19.2);
975 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
976 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
977 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
978 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
984 Test that two JS objects for the same QObject compare as equal.
986 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
988 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
989 QObject *object = component.create();
990 QVERIFY(object != 0);
992 QCOMPARE(object->property("test1").toBool(), true);
993 QCOMPARE(object->property("test2").toBool(), true);
994 QCOMPARE(object->property("test3").toBool(), true);
995 QCOMPARE(object->property("test4").toBool(), true);
996 QCOMPARE(object->property("test5").toBool(), true);
1002 Confirm bindings and alias properties can coexist.
1004 Tests for a regression where the binding would not reevaluate.
1006 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1008 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1009 QObject *object = component.create();
1010 QVERIFY(object != 0);
1012 QCOMPARE(object->property("c2").toInt(), 3);
1013 QCOMPARE(object->property("c3").toInt(), 3);
1015 object->setProperty("c2", QVariant(19));
1017 QCOMPARE(object->property("c2").toInt(), 19);
1018 QCOMPARE(object->property("c3").toInt(), 19);
1023 void tst_qdeclarativeecmascript::dynamicCreation_data()
1025 QTest::addColumn<QString>("method");
1026 QTest::addColumn<QString>("createdName");
1028 QTest::newRow("One") << "createOne" << "objectOne";
1029 QTest::newRow("Two") << "createTwo" << "objectTwo";
1030 QTest::newRow("Three") << "createThree" << "objectThree";
1034 Test using createQmlObject to dynamically generate an item
1035 Also using createComponent is tested.
1037 void tst_qdeclarativeecmascript::dynamicCreation()
1039 QFETCH(QString, method);
1040 QFETCH(QString, createdName);
1042 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1043 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1044 QVERIFY(object != 0);
1046 QMetaObject::invokeMethod(object, method.toUtf8());
1047 QObject *created = object->objectProperty();
1049 QCOMPARE(created->objectName(), createdName);
1055 Tests the destroy function
1057 void tst_qdeclarativeecmascript::dynamicDestruction()
1059 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1060 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1061 QVERIFY(object != 0);
1062 QDeclarativeGuard<QObject> createdQmlObject = 0;
1064 QMetaObject::invokeMethod(object, "create");
1065 createdQmlObject = object->objectProperty();
1066 QVERIFY(createdQmlObject);
1067 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1069 QMetaObject::invokeMethod(object, "killOther");
1070 QVERIFY(createdQmlObject);
1071 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1072 QVERIFY(createdQmlObject);
1073 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1074 if (createdQmlObject) {
1076 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1079 QVERIFY(!createdQmlObject);
1081 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1082 QMetaObject::invokeMethod(object, "killMe");
1085 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1090 tests that id.toString() works
1092 void tst_qdeclarativeecmascript::objectToString()
1094 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1095 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1096 QVERIFY(object != 0);
1097 QMetaObject::invokeMethod(object, "testToString");
1098 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1099 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1105 Tests bindings that indirectly cause their own deletion work.
1107 This test is best run under valgrind to ensure no invalid memory access occur.
1109 void tst_qdeclarativeecmascript::selfDeletingBinding()
1112 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1113 QObject *object = component.create();
1114 QVERIFY(object != 0);
1115 object->setProperty("triggerDelete", true);
1120 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1121 QObject *object = component.create();
1122 QVERIFY(object != 0);
1123 object->setProperty("triggerDelete", true);
1129 Test that extended object properties can be accessed.
1131 This test a regression where this used to crash. The issue was specificially
1132 for extended objects that did not include a synthesized meta object (so non-root
1133 and no synthesiszed properties).
1135 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1137 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1138 QObject *object = component.create();
1139 QVERIFY(object != 0);
1144 Test file/lineNumbers for binding/Script errors.
1146 void tst_qdeclarativeecmascript::scriptErrors()
1148 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1149 QString url = component.url().toString();
1151 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1152 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1153 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1154 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1155 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1156 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1157 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1158 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1160 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1161 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1162 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1163 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1164 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1165 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1166 QVERIFY(object != 0);
1168 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1169 emit object->basicSignal();
1171 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1172 emit object->anotherBasicSignal();
1174 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1175 emit object->thirdBasicSignal();
1181 Test file/lineNumbers for inline functions.
1183 void tst_qdeclarativeecmascript::functionErrors()
1185 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1186 QString url = component.url().toString();
1188 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1190 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1192 QObject *object = component.create();
1193 QVERIFY(object != 0);
1196 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1197 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1198 url = componentTwo.url().toString();
1199 object = componentTwo.create();
1200 QVERIFY(object != 0);
1201 warning = url + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
1202 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1203 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1208 Test various errors that can occur when assigning a property from script
1210 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1212 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1214 QString url = component.url().toString();
1216 QString warning1 = url + ":11:Error: Cannot assign [undefined] to int";
1217 QString warning2 = url + ":17:Error: Cannot assign QString to int";
1219 QTest::ignoreMessage(QtDebugMsg, warning1.toLatin1().constData());
1220 QTest::ignoreMessage(QtDebugMsg, warning2.toLatin1().constData());
1222 QObject *object = component.create();
1223 QVERIFY(object != 0);
1229 Test bindings still work when the reeval is triggered from within
1232 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1234 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1235 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1236 QVERIFY(object != 0);
1238 QCOMPARE(object->property("base").toReal(), 50.);
1239 QCOMPARE(object->property("test1").toReal(), 50.);
1240 QCOMPARE(object->property("test2").toReal(), 50.);
1242 object->basicSignal();
1244 QCOMPARE(object->property("base").toReal(), 200.);
1245 QCOMPARE(object->property("test1").toReal(), 200.);
1246 QCOMPARE(object->property("test2").toReal(), 200.);
1248 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1250 QCOMPARE(object->property("base").toReal(), 400.);
1251 QCOMPARE(object->property("test1").toReal(), 400.);
1252 QCOMPARE(object->property("test2").toReal(), 400.);
1258 Test that list properties can be iterated from ECMAScript
1260 void tst_qdeclarativeecmascript::listProperties()
1262 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1263 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1264 QVERIFY(object != 0);
1266 QCOMPARE(object->property("test1").toInt(), 21);
1267 QCOMPARE(object->property("test2").toInt(), 2);
1268 QCOMPARE(object->property("test3").toBool(), true);
1269 QCOMPARE(object->property("test4").toBool(), true);
1274 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1276 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1277 QString url = component.url().toString();
1279 QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object.";
1281 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1282 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1283 QVERIFY(object != 0);
1285 QCOMPARE(object->property("test").toBool(), false);
1287 MyQmlObject object2;
1288 MyQmlObject object3;
1289 object2.setObjectProperty(&object3);
1290 object->setObjectProperty(&object2);
1292 QCOMPARE(object->property("test").toBool(), true);
1297 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1299 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1300 QString url = component.url().toString();
1302 QString warning = component.url().toString() + ":6: Error: JS exception";
1304 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1305 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1306 QVERIFY(object != 0);
1310 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1312 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1313 QString url = component.url().toString();
1315 QString warning = component.url().toString() + ":5: Error: JS exception";
1317 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1318 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1319 QVERIFY(object != 0);
1323 static int transientErrorsMsgCount = 0;
1324 static void transientErrorsMsgHandler(QtMsgType, const char *)
1326 ++transientErrorsMsgCount;
1329 // Check that transient binding errors are not displayed
1330 void tst_qdeclarativeecmascript::transientErrors()
1333 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1335 transientErrorsMsgCount = 0;
1336 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1338 QObject *object = component.create();
1339 QVERIFY(object != 0);
1341 qInstallMsgHandler(old);
1343 QCOMPARE(transientErrorsMsgCount, 0);
1348 // One binding erroring multiple times, but then resolving
1350 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1352 transientErrorsMsgCount = 0;
1353 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1355 QObject *object = component.create();
1356 QVERIFY(object != 0);
1358 qInstallMsgHandler(old);
1360 QCOMPARE(transientErrorsMsgCount, 0);
1366 // Check that errors during shutdown are minimized
1367 void tst_qdeclarativeecmascript::shutdownErrors()
1369 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1370 QObject *object = component.create();
1371 QVERIFY(object != 0);
1373 transientErrorsMsgCount = 0;
1374 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1378 qInstallMsgHandler(old);
1379 QCOMPARE(transientErrorsMsgCount, 0);
1382 void tst_qdeclarativeecmascript::compositePropertyType()
1384 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1385 QTest::ignoreMessage(QtDebugMsg, "hello world");
1386 QObject *object = qobject_cast<QObject *>(component.create());
1391 void tst_qdeclarativeecmascript::jsObject()
1393 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1394 QObject *object = component.create();
1395 QVERIFY(object != 0);
1397 QCOMPARE(object->property("test").toInt(), 92);
1402 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1405 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1406 QObject *object = component.create();
1407 QVERIFY(object != 0);
1409 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1411 object->setProperty("setUndefined", true);
1413 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1415 object->setProperty("setUndefined", false);
1417 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1422 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1423 QObject *object = component.create();
1424 QVERIFY(object != 0);
1426 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1428 QMetaObject::invokeMethod(object, "doReset");
1430 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1437 void tst_qdeclarativeecmascript::bug1()
1439 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1440 QObject *object = component.create();
1441 QVERIFY(object != 0);
1443 QCOMPARE(object->property("test").toInt(), 14);
1445 object->setProperty("a", 11);
1447 QCOMPARE(object->property("test").toInt(), 3);
1449 object->setProperty("b", true);
1451 QCOMPARE(object->property("test").toInt(), 9);
1456 void tst_qdeclarativeecmascript::bug2()
1458 QDeclarativeComponent component(&engine);
1459 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1461 QObject *object = component.create();
1462 QVERIFY(object != 0);
1467 // Don't crash in createObject when the component has errors.
1468 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1470 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1471 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1472 QVERIFY(object != 0);
1474 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1475 QMetaObject::invokeMethod(object, "dontCrash");
1476 QObject *created = object->objectProperty();
1477 QVERIFY(created == 0);
1483 void tst_qdeclarativeecmascript::regExpBug()
1485 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1486 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1487 QVERIFY(object != 0);
1488 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1492 void tst_qdeclarativeecmascript::callQtInvokables()
1494 MyInvokableObject o;
1496 QDeclarativeEngine qmlengine;
1497 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1498 QScriptEngine *engine = &ep->scriptEngine;
1500 QStringList names; QList<QScriptValue> values;
1501 names << QLatin1String("object"); values << ep->objectClass->newQObject(&o);
1502 names << QLatin1String("undefined"); values << engine->undefinedValue();
1504 ep->globalClass->explicitSetProperty(names, values);
1506 // Non-existent methods
1508 QCOMPARE(engine->evaluate("object.method_nonexistent()").isError(), true);
1509 QCOMPARE(o.error(), false);
1510 QCOMPARE(o.invoked(), -1);
1511 QCOMPARE(o.actuals().count(), 0);
1514 QCOMPARE(engine->evaluate("object.method_nonexistent(10, 11)").isError(), true);
1515 QCOMPARE(o.error(), false);
1516 QCOMPARE(o.invoked(), -1);
1517 QCOMPARE(o.actuals().count(), 0);
1519 // Insufficient arguments
1521 QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
1522 QCOMPARE(o.error(), false);
1523 QCOMPARE(o.invoked(), -1);
1524 QCOMPARE(o.actuals().count(), 0);
1527 QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
1528 QCOMPARE(o.error(), false);
1529 QCOMPARE(o.invoked(), -1);
1530 QCOMPARE(o.actuals().count(), 0);
1532 // Excessive arguments
1534 QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
1535 QCOMPARE(o.error(), false);
1536 QCOMPARE(o.invoked(), 8);
1537 QCOMPARE(o.actuals().count(), 1);
1538 QCOMPARE(o.actuals().at(0), QVariant(10));
1541 QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
1542 QCOMPARE(o.error(), false);
1543 QCOMPARE(o.invoked(), 9);
1544 QCOMPARE(o.actuals().count(), 2);
1545 QCOMPARE(o.actuals().at(0), QVariant(10));
1546 QCOMPARE(o.actuals().at(1), QVariant(11));
1548 // Test return types
1550 QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
1551 QCOMPARE(o.error(), false);
1552 QCOMPARE(o.invoked(), 0);
1553 QCOMPARE(o.actuals().count(), 0);
1556 QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
1557 QCOMPARE(o.error(), false);
1558 QCOMPARE(o.invoked(), 1);
1559 QCOMPARE(o.actuals().count(), 0);
1562 QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.75)));
1563 QCOMPARE(o.error(), false);
1564 QCOMPARE(o.invoked(), 2);
1565 QCOMPARE(o.actuals().count(), 0);
1569 QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
1570 QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
1571 QCOMPARE(o.error(), false);
1572 QCOMPARE(o.invoked(), 3);
1573 QCOMPARE(o.actuals().count(), 0);
1578 QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
1579 QVERIFY(ret.isQObject());
1580 QCOMPARE(ret.toQObject(), (QObject *)&o);
1581 QCOMPARE(o.error(), false);
1582 QCOMPARE(o.invoked(), 4);
1583 QCOMPARE(o.actuals().count(), 0);
1587 QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
1588 QCOMPARE(o.error(), false);
1589 QCOMPARE(o.invoked(), 5);
1590 QCOMPARE(o.actuals().count(), 0);
1594 QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
1595 QVERIFY(ret.isString());
1596 QCOMPARE(ret.toString(), QString("Hello world"));
1597 QCOMPARE(o.error(), false);
1598 QCOMPARE(o.invoked(), 6);
1599 QCOMPARE(o.actuals().count(), 0);
1603 QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
1604 QCOMPARE(o.error(), false);
1605 QCOMPARE(o.invoked(), 7);
1606 QCOMPARE(o.actuals().count(), 0);
1610 QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
1611 QCOMPARE(o.error(), false);
1612 QCOMPARE(o.invoked(), 8);
1613 QCOMPARE(o.actuals().count(), 1);
1614 QCOMPARE(o.actuals().at(0), QVariant(94));
1617 QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
1618 QCOMPARE(o.error(), false);
1619 QCOMPARE(o.invoked(), 8);
1620 QCOMPARE(o.actuals().count(), 1);
1621 QCOMPARE(o.actuals().at(0), QVariant(94));
1624 QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
1625 QCOMPARE(o.error(), false);
1626 QCOMPARE(o.invoked(), 8);
1627 QCOMPARE(o.actuals().count(), 1);
1628 QCOMPARE(o.actuals().at(0), QVariant(0));
1631 QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
1632 QCOMPARE(o.error(), false);
1633 QCOMPARE(o.invoked(), 8);
1634 QCOMPARE(o.actuals().count(), 1);
1635 QCOMPARE(o.actuals().at(0), QVariant(0));
1638 QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
1639 QCOMPARE(o.error(), false);
1640 QCOMPARE(o.invoked(), 8);
1641 QCOMPARE(o.actuals().count(), 1);
1642 QCOMPARE(o.actuals().at(0), QVariant(0));
1645 QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
1646 QCOMPARE(o.error(), false);
1647 QCOMPARE(o.invoked(), 8);
1648 QCOMPARE(o.actuals().count(), 1);
1649 QCOMPARE(o.actuals().at(0), QVariant(0));
1652 QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
1653 QCOMPARE(o.error(), false);
1654 QCOMPARE(o.invoked(), 9);
1655 QCOMPARE(o.actuals().count(), 2);
1656 QCOMPARE(o.actuals().at(0), QVariant(122));
1657 QCOMPARE(o.actuals().at(1), QVariant(9));
1660 QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
1661 QCOMPARE(o.error(), false);
1662 QCOMPARE(o.invoked(), 10);
1663 QCOMPARE(o.actuals().count(), 1);
1664 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1667 QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
1668 QCOMPARE(o.error(), false);
1669 QCOMPARE(o.invoked(), 10);
1670 QCOMPARE(o.actuals().count(), 1);
1671 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1674 QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
1675 QCOMPARE(o.error(), false);
1676 QCOMPARE(o.invoked(), 10);
1677 QCOMPARE(o.actuals().count(), 1);
1678 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1681 QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
1682 QCOMPARE(o.error(), false);
1683 QCOMPARE(o.invoked(), 10);
1684 QCOMPARE(o.actuals().count(), 1);
1685 QCOMPARE(o.actuals().at(0), QVariant(0));
1688 QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
1689 QCOMPARE(o.error(), false);
1690 QCOMPARE(o.invoked(), 10);
1691 QCOMPARE(o.actuals().count(), 1);
1692 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1695 QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
1696 QCOMPARE(o.error(), false);
1697 QCOMPARE(o.invoked(), 10);
1698 QCOMPARE(o.actuals().count(), 1);
1699 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1702 QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
1703 QCOMPARE(o.error(), false);
1704 QCOMPARE(o.invoked(), 11);
1705 QCOMPARE(o.actuals().count(), 1);
1706 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1709 QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
1710 QCOMPARE(o.error(), false);
1711 QCOMPARE(o.invoked(), 11);
1712 QCOMPARE(o.actuals().count(), 1);
1713 QCOMPARE(o.actuals().at(0), QVariant("19"));
1717 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1718 QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
1719 QCOMPARE(o.error(), false);
1720 QCOMPARE(o.invoked(), 11);
1721 QCOMPARE(o.actuals().count(), 1);
1722 QCOMPARE(o.actuals().at(0), QVariant(expected));
1726 QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
1727 QCOMPARE(o.error(), false);
1728 QCOMPARE(o.invoked(), 11);
1729 QCOMPARE(o.actuals().count(), 1);
1730 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1733 QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
1734 QCOMPARE(o.error(), false);
1735 QCOMPARE(o.invoked(), 11);
1736 QCOMPARE(o.actuals().count(), 1);
1737 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1740 QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
1741 QCOMPARE(o.error(), false);
1742 QCOMPARE(o.invoked(), 12);
1743 QCOMPARE(o.actuals().count(), 1);
1744 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1747 QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
1748 QCOMPARE(o.error(), false);
1749 QCOMPARE(o.invoked(), 12);
1750 QCOMPARE(o.actuals().count(), 1);
1751 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1754 QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
1755 QCOMPARE(o.error(), false);
1756 QCOMPARE(o.invoked(), 12);
1757 QCOMPARE(o.actuals().count(), 1);
1758 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1761 QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
1762 QCOMPARE(o.error(), false);
1763 QCOMPARE(o.invoked(), 12);
1764 QCOMPARE(o.actuals().count(), 1);
1765 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1768 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
1769 QCOMPARE(o.error(), false);
1770 QCOMPARE(o.invoked(), 12);
1771 QCOMPARE(o.actuals().count(), 1);
1772 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1775 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
1776 QCOMPARE(o.error(), false);
1777 QCOMPARE(o.invoked(), 12);
1778 QCOMPARE(o.actuals().count(), 1);
1779 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1782 QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
1783 QCOMPARE(o.error(), false);
1784 QCOMPARE(o.invoked(), 13);
1785 QCOMPARE(o.actuals().count(), 1);
1786 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1789 QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
1790 QCOMPARE(o.error(), false);
1791 QCOMPARE(o.invoked(), 13);
1792 QCOMPARE(o.actuals().count(), 1);
1793 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1796 QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
1797 QCOMPARE(o.error(), false);
1798 QCOMPARE(o.invoked(), 13);
1799 QCOMPARE(o.actuals().count(), 1);
1800 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1803 QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
1804 QCOMPARE(o.error(), false);
1805 QCOMPARE(o.invoked(), 13);
1806 QCOMPARE(o.actuals().count(), 1);
1807 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1810 QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
1811 QCOMPARE(o.error(), false);
1812 QCOMPARE(o.invoked(), 13);
1813 QCOMPARE(o.actuals().count(), 1);
1814 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1817 QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
1818 QCOMPARE(o.error(), false);
1819 QCOMPARE(o.invoked(), 14);
1820 QCOMPARE(o.actuals().count(), 1);
1821 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1824 QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
1825 QCOMPARE(o.error(), false);
1826 QCOMPARE(o.invoked(), 14);
1827 QCOMPARE(o.actuals().count(), 1);
1828 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1831 QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
1832 QCOMPARE(o.error(), false);
1833 QCOMPARE(o.invoked(), 14);
1834 QCOMPARE(o.actuals().count(), 1);
1835 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1838 QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
1839 QCOMPARE(o.error(), false);
1840 QCOMPARE(o.invoked(), 14);
1841 QCOMPARE(o.actuals().count(), 1);
1842 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1845 QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
1846 QCOMPARE(o.error(), false);
1847 QCOMPARE(o.invoked(), 15);
1848 QCOMPARE(o.actuals().count(), 2);
1849 QCOMPARE(o.actuals().at(0), QVariant(4));
1850 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1853 QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
1854 QCOMPARE(o.error(), false);
1855 QCOMPARE(o.invoked(), 15);
1856 QCOMPARE(o.actuals().count(), 2);
1857 QCOMPARE(o.actuals().at(0), QVariant(8));
1858 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1861 QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
1862 QCOMPARE(o.error(), false);
1863 QCOMPARE(o.invoked(), 15);
1864 QCOMPARE(o.actuals().count(), 2);
1865 QCOMPARE(o.actuals().at(0), QVariant(3));
1866 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1869 QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
1870 QCOMPARE(o.error(), false);
1871 QCOMPARE(o.invoked(), 15);
1872 QCOMPARE(o.actuals().count(), 2);
1873 QCOMPARE(o.actuals().at(0), QVariant(44));
1874 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1877 QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
1878 QCOMPARE(o.error(), false);
1879 QCOMPARE(o.invoked(), -1);
1880 QCOMPARE(o.actuals().count(), 0);
1883 QCOMPARE(engine->evaluate("object.method_overload(10)").isUndefined(), true);
1884 QCOMPARE(o.error(), false);
1885 QCOMPARE(o.invoked(), 16);
1886 QCOMPARE(o.actuals().count(), 1);
1887 QCOMPARE(o.actuals().at(0), QVariant(10));
1890 QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
1891 QCOMPARE(o.error(), false);
1892 QCOMPARE(o.invoked(), 17);
1893 QCOMPARE(o.actuals().count(), 2);
1894 QCOMPARE(o.actuals().at(0), QVariant(10));
1895 QCOMPARE(o.actuals().at(1), QVariant(11));
1898 QCOMPARE(engine->evaluate("object.method_overload(\"Hello\")").isUndefined(), true);
1899 QCOMPARE(o.error(), false);
1900 QCOMPARE(o.invoked(), 18);
1901 QCOMPARE(o.actuals().count(), 1);
1902 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1905 QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
1906 QCOMPARE(o.error(), false);
1907 QCOMPARE(o.invoked(), 19);
1908 QCOMPARE(o.actuals().count(), 1);
1909 QCOMPARE(o.actuals().at(0), QVariant(9));
1912 QVERIFY(engine->evaluate("object.method_default(10)").strictlyEquals(QScriptValue(19)));
1913 QCOMPARE(o.error(), false);
1914 QCOMPARE(o.invoked(), 20);
1915 QCOMPARE(o.actuals().count(), 2);
1916 QCOMPARE(o.actuals().at(0), QVariant(10));
1917 QCOMPARE(o.actuals().at(1), QVariant(19));
1920 QVERIFY(engine->evaluate("object.method_default(10, 13)").strictlyEquals(QScriptValue(13)));
1921 QCOMPARE(o.error(), false);
1922 QCOMPARE(o.invoked(), 20);
1923 QCOMPARE(o.actuals().count(), 2);
1924 QCOMPARE(o.actuals().at(0), QVariant(10));
1925 QCOMPARE(o.actuals().at(1), QVariant(13));
1928 QCOMPARE(engine->evaluate("object.method_inherited(9)").isUndefined(), true);
1929 QCOMPARE(o.error(), false);
1930 QCOMPARE(o.invoked(), -3);
1931 QCOMPARE(o.actuals().count(), 1);
1932 QCOMPARE(o.actuals().at(0), QVariant(9));
1935 QCOMPARE(engine->evaluate("object.method_QVariant(9)").isUndefined(), true);
1936 QCOMPARE(o.error(), false);
1937 QCOMPARE(o.invoked(), 21);
1938 QCOMPARE(o.actuals().count(), 2);
1939 QCOMPARE(o.actuals().at(0), QVariant(9));
1940 QCOMPARE(o.actuals().at(1), QVariant());
1943 QCOMPARE(engine->evaluate("object.method_QVariant(\"Hello\", \"World\")").isUndefined(), true);
1944 QCOMPARE(o.error(), false);
1945 QCOMPARE(o.invoked(), 21);
1946 QCOMPARE(o.actuals().count(), 2);
1947 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1948 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
1951 // QTBUG-13047 (check that you can pass registered object types as args)
1952 void tst_qdeclarativeecmascript::invokableObjectArg()
1954 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
1956 QObject *o = component.create();
1958 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
1960 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
1965 // QTBUG-13047 (check that you can return registered object types from methods)
1966 void tst_qdeclarativeecmascript::invokableObjectRet()
1968 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
1970 QObject *o = component.create();
1972 QCOMPARE(o->property("test").toBool(), true);
1977 void tst_qdeclarativeecmascript::listToVariant()
1979 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
1981 MyQmlContainer container;
1983 QDeclarativeContext context(engine.rootContext());
1984 context.setContextObject(&container);
1986 QObject *object = component.create(&context);
1987 QVERIFY(object != 0);
1989 QVariant v = object->property("test");
1990 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
1991 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
1997 void tst_qdeclarativeecmascript::multiEngineObject()
2000 obj.setStringProperty("Howdy planet");
2002 QDeclarativeEngine e1;
2003 e1.rootContext()->setContextProperty("thing", &obj);
2004 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2006 QDeclarativeEngine e2;
2007 e2.rootContext()->setContextProperty("thing", &obj);
2008 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2010 QObject *o1 = c1.create();
2011 QObject *o2 = c2.create();
2013 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2014 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2020 // Test that references to QObjects are cleanup when the object is destroyed
2021 void tst_qdeclarativeecmascript::deletedObject()
2023 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2025 QObject *object = component.create();
2027 QCOMPARE(object->property("test1").toBool(), true);
2028 QCOMPARE(object->property("test2").toBool(), true);
2029 QCOMPARE(object->property("test3").toBool(), true);
2030 QCOMPARE(object->property("test4").toBool(), true);
2035 void tst_qdeclarativeecmascript::attachedPropertyScope()
2037 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2039 QObject *object = component.create();
2040 QVERIFY(object != 0);
2042 MyQmlAttachedObject *attached =
2043 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2044 QVERIFY(attached != 0);
2046 QCOMPARE(object->property("value2").toInt(), 0);
2048 attached->emitMySignal();
2050 QCOMPARE(object->property("value2").toInt(), 9);
2055 void tst_qdeclarativeecmascript::scriptConnect()
2058 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2060 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2061 QVERIFY(object != 0);
2063 QCOMPARE(object->property("test").toBool(), false);
2064 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2065 QCOMPARE(object->property("test").toBool(), true);
2071 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2073 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2074 QVERIFY(object != 0);
2076 QCOMPARE(object->property("test").toBool(), false);
2077 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2078 QCOMPARE(object->property("test").toBool(), true);
2084 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2086 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2087 QVERIFY(object != 0);
2089 QCOMPARE(object->property("test").toBool(), false);
2090 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2091 QCOMPARE(object->property("test").toBool(), true);
2097 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2099 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2100 QVERIFY(object != 0);
2102 QCOMPARE(object->methodCalled(), false);
2103 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2104 QCOMPARE(object->methodCalled(), true);
2110 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2112 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2113 QVERIFY(object != 0);
2115 QCOMPARE(object->methodCalled(), false);
2116 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2117 QCOMPARE(object->methodCalled(), true);
2123 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2125 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2126 QVERIFY(object != 0);
2128 QCOMPARE(object->property("test").toInt(), 0);
2129 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2130 QCOMPARE(object->property("test").toInt(), 2);
2136 void tst_qdeclarativeecmascript::scriptDisconnect()
2139 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2141 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2142 QVERIFY(object != 0);
2144 QCOMPARE(object->property("test").toInt(), 0);
2145 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2146 QCOMPARE(object->property("test").toInt(), 1);
2147 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2148 QCOMPARE(object->property("test").toInt(), 2);
2149 emit object->basicSignal();
2150 QCOMPARE(object->property("test").toInt(), 2);
2151 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2152 QCOMPARE(object->property("test").toInt(), 2);
2158 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2160 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2161 QVERIFY(object != 0);
2163 QCOMPARE(object->property("test").toInt(), 0);
2164 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2165 QCOMPARE(object->property("test").toInt(), 1);
2166 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2167 QCOMPARE(object->property("test").toInt(), 2);
2168 emit object->basicSignal();
2169 QCOMPARE(object->property("test").toInt(), 2);
2170 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2171 QCOMPARE(object->property("test").toInt(), 2);
2177 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2179 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2180 QVERIFY(object != 0);
2182 QCOMPARE(object->property("test").toInt(), 0);
2183 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2184 QCOMPARE(object->property("test").toInt(), 1);
2185 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2186 QCOMPARE(object->property("test").toInt(), 2);
2187 emit object->basicSignal();
2188 QCOMPARE(object->property("test").toInt(), 2);
2189 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2190 QCOMPARE(object->property("test").toInt(), 3);
2195 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2197 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2198 QVERIFY(object != 0);
2200 QCOMPARE(object->property("test").toInt(), 0);
2201 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2202 QCOMPARE(object->property("test").toInt(), 1);
2203 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2204 QCOMPARE(object->property("test").toInt(), 2);
2205 emit object->basicSignal();
2206 QCOMPARE(object->property("test").toInt(), 2);
2207 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2208 QCOMPARE(object->property("test").toInt(), 3);
2214 class OwnershipObject : public QObject
2218 OwnershipObject() { object = new QObject; }
2220 QPointer<QObject> object;
2223 QObject *getObject() { return object; }
2226 void tst_qdeclarativeecmascript::ownership()
2228 OwnershipObject own;
2229 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2230 context->setContextObject(&own);
2233 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2235 QVERIFY(own.object != 0);
2237 QObject *object = component.create(context);
2238 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2240 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2242 QVERIFY(own.object == 0);
2247 own.object = new QObject(&own);
2250 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2252 QVERIFY(own.object != 0);
2254 QObject *object = component.create(context);
2255 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2257 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2259 QVERIFY(own.object != 0);
2267 class CppOwnershipReturnValue : public QObject
2271 CppOwnershipReturnValue() : value(0) {}
2272 ~CppOwnershipReturnValue() { delete value; }
2274 Q_INVOKABLE QObject *create() {
2275 value = new QObject;
2276 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2280 Q_INVOKABLE MyQmlObject *createQmlObject() {
2281 MyQmlObject *rv = new MyQmlObject;
2286 QPointer<QObject> value;
2290 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2291 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2293 CppOwnershipReturnValue source;
2296 QDeclarativeEngine engine;
2297 engine.rootContext()->setContextProperty("source", &source);
2299 QVERIFY(source.value == 0);
2301 QDeclarativeComponent component(&engine);
2302 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2304 QObject *object = component.create();
2306 QVERIFY(object != 0);
2307 QVERIFY(source.value != 0);
2312 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2314 QVERIFY(source.value != 0);
2318 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2320 CppOwnershipReturnValue source;
2323 QDeclarativeEngine engine;
2324 engine.rootContext()->setContextProperty("source", &source);
2326 QVERIFY(source.value == 0);
2328 QDeclarativeComponent component(&engine);
2329 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2331 QObject *object = component.create();
2333 QVERIFY(object != 0);
2334 QVERIFY(source.value != 0);
2339 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2341 QVERIFY(source.value == 0);
2344 class QListQObjectMethodsObject : public QObject
2348 QListQObjectMethodsObject() {
2349 m_objects.append(new MyQmlObject());
2350 m_objects.append(new MyQmlObject());
2353 ~QListQObjectMethodsObject() {
2354 qDeleteAll(m_objects);
2358 QList<QObject *> getObjects() { return m_objects; }
2361 QList<QObject *> m_objects;
2364 // Tests that returning a QList<QObject*> from a method works
2365 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2367 QListQObjectMethodsObject obj;
2368 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2369 context->setContextObject(&obj);
2371 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2373 QObject *object = component.create(context);
2375 QCOMPARE(object->property("test").toInt(), 2);
2376 QCOMPARE(object->property("test2").toBool(), true);
2383 void tst_qdeclarativeecmascript::strictlyEquals()
2385 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2387 QObject *object = component.create();
2388 QVERIFY(object != 0);
2390 QCOMPARE(object->property("test1").toBool(), true);
2391 QCOMPARE(object->property("test2").toBool(), true);
2392 QCOMPARE(object->property("test3").toBool(), true);
2393 QCOMPARE(object->property("test4").toBool(), true);
2394 QCOMPARE(object->property("test5").toBool(), true);
2395 QCOMPARE(object->property("test6").toBool(), true);
2396 QCOMPARE(object->property("test7").toBool(), true);
2397 QCOMPARE(object->property("test8").toBool(), true);
2402 void tst_qdeclarativeecmascript::compiled()
2404 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2406 QObject *object = component.create();
2407 QVERIFY(object != 0);
2409 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2410 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2411 QCOMPARE(object->property("test3").toBool(), true);
2412 QCOMPARE(object->property("test4").toBool(), false);
2413 QCOMPARE(object->property("test5").toBool(), false);
2414 QCOMPARE(object->property("test6").toBool(), true);
2416 QCOMPARE(object->property("test7").toInt(), 185);
2417 QCOMPARE(object->property("test8").toInt(), 167);
2418 QCOMPARE(object->property("test9").toBool(), true);
2419 QCOMPARE(object->property("test10").toBool(), false);
2420 QCOMPARE(object->property("test11").toBool(), false);
2421 QCOMPARE(object->property("test12").toBool(), true);
2423 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2424 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2425 QCOMPARE(object->property("test15").toBool(), false);
2426 QCOMPARE(object->property("test16").toBool(), true);
2428 QCOMPARE(object->property("test17").toInt(), 5);
2429 QCOMPARE(object->property("test18").toReal(), qreal(176));
2430 QCOMPARE(object->property("test19").toInt(), 7);
2431 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2432 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2433 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2434 QCOMPARE(object->property("test23").toBool(), true);
2435 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2436 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2441 // Test that numbers assigned in bindings as strings work consistently
2442 void tst_qdeclarativeecmascript::numberAssignment()
2444 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2446 QObject *object = component.create();
2447 QVERIFY(object != 0);
2449 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2450 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2451 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2452 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2453 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2455 QCOMPARE(object->property("test5"), QVariant((int)7));
2456 QCOMPARE(object->property("test6"), QVariant((int)7));
2457 QCOMPARE(object->property("test7"), QVariant((int)6));
2458 QCOMPARE(object->property("test8"), QVariant((int)6));
2460 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2461 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2462 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2463 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2468 void tst_qdeclarativeecmascript::propertySplicing()
2470 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2472 QObject *object = component.create();
2473 QVERIFY(object != 0);
2475 QCOMPARE(object->property("test").toBool(), true);
2481 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2483 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2485 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2486 QVERIFY(object != 0);
2488 MyQmlObject::MyType type;
2489 type.value = 0x8971123;
2490 emit object->signalWithUnknownType(type);
2492 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2494 QCOMPARE(result.value, type.value);
2500 void tst_qdeclarativeecmascript::moduleApi()
2502 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2503 QObject *object = component.create();
2504 QVERIFY(object != 0);
2505 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2506 QCOMPARE(object->property("scriptTest").toInt(), 13);
2507 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2508 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2509 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2510 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2511 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2514 // test that caching of module apis works correctly.
2515 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2516 object = componentTwo.create();
2517 QVERIFY(object != 0);
2518 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2519 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2520 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2523 // test that writing to a property of module apis works correctly.
2524 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2525 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2526 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2527 object = componentThree.create();
2528 QVERIFY(object != 0);
2529 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2530 QCOMPARE(object->property("writableProperty").toInt(), 50);
2531 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2532 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2533 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2534 QCOMPARE(object->property("writableProperty").toInt(), 30);
2537 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2538 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2539 object = failOne.create();
2540 QVERIFY(object == 0); // should have failed: invalid major version
2542 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2543 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2544 object = failTwo.create();
2545 QVERIFY(object == 0); // should have failed: invalid minor version
2548 void tst_qdeclarativeecmascript::importScripts()
2550 QObject *object = 0;
2552 // first, ensure that the required behaviour works.
2553 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2554 object = component.create();
2555 QVERIFY(object != 0);
2556 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2557 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2558 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2559 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2562 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2563 object = componentTwo.create();
2564 QVERIFY(object != 0);
2565 QCOMPARE(object->property("componentError"), QVariant(5));
2568 // then, ensure that unintended behaviour does not work.
2569 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2570 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Result of expression 'TestScriptImport.ImportOneJs' [undefined] is not an object.");
2571 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2572 object = failOneComponent.create();
2573 QVERIFY(object != 0);
2574 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2576 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2577 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2578 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2579 object = failTwoComponent.create();
2580 QVERIFY(object != 0);
2581 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2583 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2584 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Result of expression 'testQtObject.TestModuleImport.JsQtTest' [undefined] is not an object.");
2585 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2586 object = failThreeComponent.create();
2587 QVERIFY(object != 0);
2588 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2590 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2591 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2592 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2593 object = failFourComponent.create();
2594 QVERIFY(object != 0);
2595 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2597 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2598 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2599 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2600 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2601 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2602 object = failFiveComponent.create();
2603 QVERIFY(object != 0);
2604 QCOMPARE(object->property("componentError"), QVariant(0));
2607 // also, test that importing scripts with .pragma library works as required
2608 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2609 object = pragmaLibraryComponent.create();
2610 QVERIFY(object != 0);
2611 QCOMPARE(object->property("testValue"), QVariant(31));
2614 // and that .pragma library scripts don't inherit imports from any .qml file
2615 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2616 object = pragmaLibraryComponentTwo.create();
2617 QVERIFY(object != 0);
2618 QCOMPARE(object->property("testValue"), QVariant(0));
2622 void tst_qdeclarativeecmascript::scarceResources()
2624 QPixmap origPixmap(100, 100);
2625 origPixmap.fill(Qt::blue);
2627 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2628 ScarceResourceObject *eo = 0;
2629 QObject *object = 0;
2631 // in the following three cases, the instance created from the component
2632 // has a property which is a copy of the scarce resource; hence, the
2633 // resource should NOT be detached prior to deletion of the object instance,
2634 // unless the resource is destroyed explicitly.
2635 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2636 object = component.create();
2637 QVERIFY(object != 0);
2638 QVERIFY(object->property("scarceResourceCopy").isValid());
2639 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2640 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2641 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2642 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2645 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2646 object = componentTwo.create();
2647 QVERIFY(object != 0);
2648 QVERIFY(object->property("scarceResourceCopy").isValid());
2649 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2650 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2651 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2652 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2655 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2656 object = componentThree.create();
2657 QVERIFY(object != 0);
2658 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2659 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2660 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2661 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2664 // in the following three cases, no other copy should exist in memory,
2665 // and so it should be detached (unless explicitly preserved).
2666 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2667 object = componentFour.create();
2668 QVERIFY(object != 0);
2669 QVERIFY(object->property("scarceResourceTest").isValid());
2670 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2671 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2672 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2673 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2676 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2677 object = componentFive.create();
2678 QVERIFY(object != 0);
2679 QVERIFY(object->property("scarceResourceTest").isValid());
2680 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2681 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2682 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2683 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2686 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2687 object = componentSix.create();
2688 QVERIFY(object != 0);
2689 QVERIFY(object->property("scarceResourceTest").isValid());
2690 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2691 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2692 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2693 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2696 // test that scarce resources are handled correctly for imports
2697 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2698 object = componentSeven.create();
2699 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2700 QVERIFY(ep->scarceResources == 0); // but they should have been released by this point.
2703 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2704 object = componentEight.create();
2705 QVERIFY(object != 0);
2706 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2707 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2710 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2711 object = componentNine.create();
2712 QVERIFY(object != 0);
2713 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2714 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2715 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2716 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2717 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2718 QVERIFY(ep->scarceResources == 0); // this will still be zero, because "preserve()" REMOVES it from this list.
2721 // test that scarce resources are handled properly in signal invocation
2722 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2723 object = componentTen.create();
2724 QVERIFY(object != 0);
2725 QObject *srsc = object->findChild<QObject*>("srsc");
2727 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2728 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2729 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2730 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2731 QMetaObject::invokeMethod(srsc, "testSignal");
2732 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2733 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2734 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2735 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2736 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2737 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2738 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2739 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2740 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2741 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2744 // test that scarce resources are handled properly from js functions in qml files
2745 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2746 object = componentEleven.create();
2747 QVERIFY(object != 0);
2748 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2749 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2750 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2751 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2752 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2753 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2754 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2755 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2756 QMetaObject::invokeMethod(object, "releaseScarceResource");
2757 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2758 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2759 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2760 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2763 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2764 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2765 object = componentTwelve.create();
2766 QVERIFY(object != 0);
2767 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2768 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2769 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2770 QString expectedWarning = QLatin1String("file://") + TEST_FILE("scarceresources/scarceResourceFunctionFail.qml").toLocalFile() + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
2771 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData()); // we expect a meaningful warning to be printed.
2772 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2773 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2774 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2775 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2776 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2780 // Test that assigning a null object works
2781 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2782 void tst_qdeclarativeecmascript::nullObjectBinding()
2784 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2786 QObject *object = component.create();
2787 QVERIFY(object != 0);
2789 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2794 // Test that bindings don't evaluate once the engine has been destroyed
2795 void tst_qdeclarativeecmascript::deletedEngine()
2797 QDeclarativeEngine *engine = new QDeclarativeEngine;
2798 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2800 QObject *object = component.create();
2801 QVERIFY(object != 0);
2803 QCOMPARE(object->property("a").toInt(), 39);
2804 object->setProperty("b", QVariant(9));
2805 QCOMPARE(object->property("a").toInt(), 117);
2809 QCOMPARE(object->property("a").toInt(), 117);
2810 object->setProperty("b", QVariant(10));
2811 QCOMPARE(object->property("a").toInt(), 117);
2816 // Test the crashing part of QTBUG-9705
2817 void tst_qdeclarativeecmascript::libraryScriptAssert()
2819 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2821 QObject *object = component.create();
2822 QVERIFY(object != 0);
2827 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2829 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2831 QObject *object = component.create();
2832 QVERIFY(object != 0);
2834 QCOMPARE(object->property("test1").toInt(), 10);
2835 QCOMPARE(object->property("test2").toInt(), 11);
2837 object->setProperty("runTest", true);
2839 QCOMPARE(object->property("test1"), QVariant());
2840 QCOMPARE(object->property("test2"), QVariant());
2846 void tst_qdeclarativeecmascript::qtbug_9792()
2848 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
2850 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2852 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
2853 QVERIFY(object != 0);
2855 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
2856 object->basicSignal();
2860 transientErrorsMsgCount = 0;
2861 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2863 object->basicSignal();
2865 qInstallMsgHandler(old);
2867 QCOMPARE(transientErrorsMsgCount, 0);
2872 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
2873 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
2875 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
2877 QObject *o = component.create();
2880 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
2881 QVERIFY(nested != 0);
2883 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
2886 nested = qvariant_cast<QObject *>(o->property("object"));
2887 QVERIFY(nested == 0);
2889 // If the bug is present, the next line will crash
2893 // Test that we shut down without stupid warnings
2894 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
2897 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
2899 QObject *o = component.create();
2901 transientErrorsMsgCount = 0;
2902 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2906 qInstallMsgHandler(old);
2908 QCOMPARE(transientErrorsMsgCount, 0);
2913 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
2915 QObject *o = component.create();
2917 transientErrorsMsgCount = 0;
2918 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2922 qInstallMsgHandler(old);
2924 QCOMPARE(transientErrorsMsgCount, 0);
2928 void tst_qdeclarativeecmascript::canAssignNullToQObject()
2931 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
2933 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2936 QVERIFY(o->objectProperty() != 0);
2938 o->setProperty("runTest", true);
2940 QVERIFY(o->objectProperty() == 0);
2946 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
2948 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2951 QVERIFY(o->objectProperty() == 0);
2957 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
2959 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
2961 QString url = component.url().toString();
2962 QString warning = url + ":4: Unable to assign a function to a property.";
2963 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
2965 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2968 QVERIFY(!o->property("a").isValid());
2973 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
2975 QFETCH(QString, triggerProperty);
2977 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
2978 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
2980 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2982 QVERIFY(!o->property("a").isValid());
2984 o->setProperty("aNumber", QVariant(5));
2985 o->setProperty(triggerProperty.toUtf8().constData(), true);
2986 QCOMPARE(o->property("a"), QVariant(50));
2988 o->setProperty("aNumber", QVariant(10));
2989 QCOMPARE(o->property("a"), QVariant(100));
2994 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
2996 QTest::addColumn<QString>("triggerProperty");
2998 QTest::newRow("assign to property") << "assignToProperty";
2999 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3001 QTest::newRow("assign to value type") << "assignToValueType";
3003 QTest::newRow("use 'this'") << "assignWithThis";
3004 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3007 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3009 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3010 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3012 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3014 QVERIFY(!o->property("a").isValid());
3016 o->setProperty("assignFuncWithoutReturn", true);
3017 QVERIFY(!o->property("a").isValid());
3019 QString url = component.url().toString();
3020 QString warning = url + ":63: Unable to assign QString to int";
3021 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3022 o->setProperty("assignWrongType", true);
3024 warning = url + ":70: Unable to assign QString to int";
3025 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3026 o->setProperty("assignWrongTypeToValueType", true);
3031 void tst_qdeclarativeecmascript::eval()
3033 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3035 QObject *o = component.create();
3038 QCOMPARE(o->property("test1").toBool(), true);
3039 QCOMPARE(o->property("test2").toBool(), true);
3040 QCOMPARE(o->property("test3").toBool(), true);
3041 QCOMPARE(o->property("test4").toBool(), true);
3042 QCOMPARE(o->property("test5").toBool(), true);
3047 void tst_qdeclarativeecmascript::function()
3049 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3051 QObject *o = component.create();
3054 QCOMPARE(o->property("test1").toBool(), true);
3055 QCOMPARE(o->property("test2").toBool(), true);
3056 QCOMPARE(o->property("test3").toBool(), true);
3061 // Test the "Qt.include" method
3062 void tst_qdeclarativeecmascript::include()
3064 // Non-library relative include
3066 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3067 QObject *o = component.create();
3070 QCOMPARE(o->property("test0").toInt(), 99);
3071 QCOMPARE(o->property("test1").toBool(), true);
3072 QCOMPARE(o->property("test2").toBool(), true);
3073 QCOMPARE(o->property("test2_1").toBool(), true);
3074 QCOMPARE(o->property("test3").toBool(), true);
3075 QCOMPARE(o->property("test3_1").toBool(), true);
3080 // Library relative include
3082 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3083 QObject *o = component.create();
3086 QCOMPARE(o->property("test0").toInt(), 99);
3087 QCOMPARE(o->property("test1").toBool(), true);
3088 QCOMPARE(o->property("test2").toBool(), true);
3089 QCOMPARE(o->property("test2_1").toBool(), true);
3090 QCOMPARE(o->property("test3").toBool(), true);
3091 QCOMPARE(o->property("test3_1").toBool(), true);
3098 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3099 QObject *o = component.create();
3102 QCOMPARE(o->property("test1").toBool(), true);
3103 QCOMPARE(o->property("test2").toBool(), true);
3104 QCOMPARE(o->property("test3").toBool(), true);
3105 QCOMPARE(o->property("test4").toBool(), true);
3106 QCOMPARE(o->property("test5").toBool(), true);
3107 QCOMPARE(o->property("test6").toBool(), true);
3112 // Including file with ".pragma library"
3114 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3115 QObject *o = component.create();
3117 QCOMPARE(o->property("test1").toInt(), 100);
3124 TestHTTPServer server(8111);
3125 QVERIFY(server.isValid());
3126 server.serveDirectory(SRCDIR "/data");
3128 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3129 QObject *o = component.create();
3132 QTRY_VERIFY(o->property("done").toBool() == true);
3133 QTRY_VERIFY(o->property("done2").toBool() == true);
3135 QCOMPARE(o->property("test1").toBool(), true);
3136 QCOMPARE(o->property("test2").toBool(), true);
3137 QCOMPARE(o->property("test3").toBool(), true);
3138 QCOMPARE(o->property("test4").toBool(), true);
3139 QCOMPARE(o->property("test5").toBool(), true);
3141 QCOMPARE(o->property("test6").toBool(), true);
3142 QCOMPARE(o->property("test7").toBool(), true);
3143 QCOMPARE(o->property("test8").toBool(), true);
3144 QCOMPARE(o->property("test9").toBool(), true);
3145 QCOMPARE(o->property("test10").toBool(), true);
3152 TestHTTPServer server(8111);
3153 QVERIFY(server.isValid());
3154 server.serveDirectory(SRCDIR "/data");
3156 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3157 QObject *o = component.create();
3160 QTRY_VERIFY(o->property("done").toBool() == true);
3162 QCOMPARE(o->property("test1").toBool(), true);
3163 QCOMPARE(o->property("test2").toBool(), true);
3164 QCOMPARE(o->property("test3").toBool(), true);
3170 void tst_qdeclarativeecmascript::qtbug_10696()
3172 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3173 QObject *o = component.create();
3178 void tst_qdeclarativeecmascript::qtbug_11606()
3180 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3181 QObject *o = component.create();
3183 QCOMPARE(o->property("test").toBool(), true);
3187 void tst_qdeclarativeecmascript::qtbug_11600()
3189 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3190 QObject *o = component.create();
3192 QCOMPARE(o->property("test").toBool(), true);
3196 // Reading and writing non-scriptable properties should fail
3197 void tst_qdeclarativeecmascript::nonscriptable()
3199 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3200 QObject *o = component.create();
3202 QCOMPARE(o->property("readOk").toBool(), true);
3203 QCOMPARE(o->property("writeOk").toBool(), true);
3207 // deleteLater() should not be callable from QML
3208 void tst_qdeclarativeecmascript::deleteLater()
3210 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3211 QObject *o = component.create();
3213 QCOMPARE(o->property("test").toBool(), true);
3217 void tst_qdeclarativeecmascript::in()
3219 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3220 QObject *o = component.create();
3222 QCOMPARE(o->property("test1").toBool(), true);
3223 QCOMPARE(o->property("test2").toBool(), true);
3227 void tst_qdeclarativeecmascript::sharedAttachedObject()
3229 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3230 QObject *o = component.create();
3232 QCOMPARE(o->property("test1").toBool(), true);
3233 QCOMPARE(o->property("test2").toBool(), true);
3238 void tst_qdeclarativeecmascript::objectName()
3240 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3241 QObject *o = component.create();
3244 QCOMPARE(o->property("test1").toString(), QString("hello"));
3245 QCOMPARE(o->property("test2").toString(), QString("ell"));
3247 o->setObjectName("world");
3249 QCOMPARE(o->property("test1").toString(), QString("world"));
3250 QCOMPARE(o->property("test2").toString(), QString("orl"));
3255 void tst_qdeclarativeecmascript::writeRemovesBinding()
3257 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3258 QObject *o = component.create();
3261 QCOMPARE(o->property("test").toBool(), true);
3266 // Test bindings assigned to alias properties actually assign to the alias' target
3267 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3269 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3270 QObject *o = component.create();
3273 QCOMPARE(o->property("test").toBool(), true);
3278 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3279 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3282 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3283 QObject *o = component.create();
3286 QCOMPARE(o->property("test").toBool(), true);
3292 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3293 QObject *o = component.create();
3296 QCOMPARE(o->property("test").toBool(), true);
3302 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3303 QObject *o = component.create();
3306 QCOMPARE(o->property("test").toBool(), true);
3312 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3313 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3316 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3317 QObject *o = component.create();
3320 QCOMPARE(o->property("test").toBool(), true);
3326 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3327 QObject *o = component.create();
3330 QCOMPARE(o->property("test").toBool(), true);
3336 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3337 QObject *o = component.create();
3340 QCOMPARE(o->property("test").toBool(), true);
3346 void tst_qdeclarativeecmascript::revisionErrors()
3349 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3350 QString url = component.url().toString();
3352 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3353 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3354 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3356 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3357 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3358 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3359 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3360 QVERIFY(object != 0);
3364 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3365 QString url = component.url().toString();
3367 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3368 // method2, prop2 from MyRevisionedClass not available
3369 // method4, prop4 from MyRevisionedSubclass not available
3370 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3371 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3372 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3373 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3374 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3376 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3377 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3378 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3379 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3380 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3381 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3382 QVERIFY(object != 0);
3386 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3387 QString url = component.url().toString();
3389 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3390 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3391 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3392 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3393 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3394 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3395 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3396 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3397 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3398 QVERIFY(object != 0);
3403 void tst_qdeclarativeecmascript::revision()
3406 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3407 QString url = component.url().toString();
3409 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3410 QVERIFY(object != 0);
3414 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3415 QString url = component.url().toString();
3417 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3418 QVERIFY(object != 0);
3422 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3423 QString url = component.url().toString();
3425 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3426 QVERIFY(object != 0);
3429 // Test that non-root classes can resolve revisioned methods
3431 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3433 QObject *object = component.create();
3434 QVERIFY(object != 0);
3435 QCOMPARE(object->property("test").toReal(), 11.);
3440 // Test for QScriptDeclarativeClass::pushCleanContext()
3441 void tst_qdeclarativeecmascript::pushCleanContext()
3443 QScriptEngine engine;
3444 engine.globalObject().setProperty("a", 6);
3445 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3447 // First confirm pushContext() behaves as we expect
3448 QScriptValue object = engine.newObject();
3449 object.setProperty("a", 15);
3450 QScriptContext *context1 = engine.pushContext();
3451 context1->pushScope(object);
3452 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3454 QScriptContext *context2 = engine.pushContext();
3456 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3457 QScriptValue func1 = engine.evaluate("(function() { return a; })");
3459 // Now check that pushCleanContext() works
3460 QScriptDeclarativeClass::pushCleanContext(&engine);
3461 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3462 QScriptValue func2 = engine.evaluate("(function() { return a; })");
3464 engine.popContext();
3465 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3467 engine.popContext();
3468 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3470 engine.popContext();
3471 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3473 // Check that function objects created in these contexts work
3474 QCOMPARE(func1.call().toInt32(), 15);
3475 QCOMPARE(func2.call().toInt32(), 6);
3478 void tst_qdeclarativeecmascript::realToInt()
3480 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3481 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3482 QVERIFY(object != 0);
3484 QMetaObject::invokeMethod(object, "test1");
3485 QCOMPARE(object->value(), int(4));
3486 QMetaObject::invokeMethod(object, "test2");
3487 QCOMPARE(object->value(), int(8));
3490 QTEST_MAIN(tst_qdeclarativeecmascript)
3492 #include "tst_qdeclarativeecmascript.moc"