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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <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/qscriptdeclarativeclass_p.h>
53 #include "testtypes.h"
54 #include "testhttpserver.h"
55 #include "../../../shared/util.h"
58 // In Symbian OS test data is located in applications private dir
63 This test covers evaluation of ECMAScript expressions and bindings from within
64 QML. This does not include static QML language issues.
66 Static QML language issues are covered in qmllanguage
68 inline QUrl TEST_FILE(const QString &filename)
70 QFileInfo fileInfo(__FILE__);
71 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
74 inline QUrl TEST_FILE(const char *filename)
76 return TEST_FILE(QLatin1String(filename));
79 class tst_qdeclarativeecmascript : public QObject
83 tst_qdeclarativeecmascript() {}
87 void assignBasicTypes();
88 void idShortcutInvalidates();
89 void boolPropertiesEvaluateAsBool();
91 void signalAssignment();
93 void basicExpressions();
94 void basicExpressions_data();
95 void arrayExpressions();
96 void contextPropertiesTriggerReeval();
97 void objectPropertiesTriggerReeval();
98 void deferredProperties();
99 void deferredPropertiesErrors();
100 void extensionObjects();
101 void overrideExtensionProperties();
102 void attachedProperties();
104 void valueTypeFunctions();
105 void constantsOverrideBindings();
106 void outerBindingOverridesInnerBinding();
107 void aliasPropertyAndBinding();
108 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();
150 void propertyChangeSlots();
154 void dynamicCreationCrash();
156 void nullObjectBinding();
157 void deletedEngine();
158 void libraryScriptAssert();
159 void variantsAssignedUndefined();
161 void qtcreatorbug_1289();
162 void noSpuriousWarningsAtShutdown();
163 void canAssignNullToQObject();
164 void functionAssignment_fromBinding();
165 void functionAssignment_fromJS();
166 void functionAssignment_fromJS_data();
167 void functionAssignmentfromJS_invalid();
173 void nonscriptable();
176 void sharedAttachedObject();
178 void writeRemovesBinding();
179 void aliasBindingsAssignCorrectly();
180 void aliasBindingsOverrideTarget();
181 void aliasWritesOverrideBindings();
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);
961 // In 4.7, non-library javascript files that had no imports shared the imports of their
963 void tst_qdeclarativeecmascript::importScope()
965 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
966 QObject *o = component.create();
969 QCOMPARE(o->property("test").toInt(), 240);
975 Tests that "any" type passes through a synthesized signal parameter. This
976 is essentially a test of QDeclarativeMetaType::copy()
978 void tst_qdeclarativeecmascript::signalParameterTypes()
980 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
981 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
982 QVERIFY(object != 0);
984 emit object->basicSignal();
986 QCOMPARE(object->property("intProperty").toInt(), 10);
987 QCOMPARE(object->property("realProperty").toReal(), 19.2);
988 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
989 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
990 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
991 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
997 Test that two JS objects for the same QObject compare as equal.
999 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1001 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1002 QObject *object = component.create();
1003 QVERIFY(object != 0);
1005 QCOMPARE(object->property("test1").toBool(), true);
1006 QCOMPARE(object->property("test2").toBool(), true);
1007 QCOMPARE(object->property("test3").toBool(), true);
1008 QCOMPARE(object->property("test4").toBool(), true);
1009 QCOMPARE(object->property("test5").toBool(), true);
1015 Confirm bindings and alias properties can coexist.
1017 Tests for a regression where the binding would not reevaluate.
1019 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1021 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1022 QObject *object = component.create();
1023 QVERIFY(object != 0);
1025 QCOMPARE(object->property("c2").toInt(), 3);
1026 QCOMPARE(object->property("c3").toInt(), 3);
1028 object->setProperty("c2", QVariant(19));
1030 QCOMPARE(object->property("c2").toInt(), 19);
1031 QCOMPARE(object->property("c3").toInt(), 19);
1036 void tst_qdeclarativeecmascript::dynamicCreation_data()
1038 QTest::addColumn<QString>("method");
1039 QTest::addColumn<QString>("createdName");
1041 QTest::newRow("One") << "createOne" << "objectOne";
1042 QTest::newRow("Two") << "createTwo" << "objectTwo";
1043 QTest::newRow("Three") << "createThree" << "objectThree";
1047 Test using createQmlObject to dynamically generate an item
1048 Also using createComponent is tested.
1050 void tst_qdeclarativeecmascript::dynamicCreation()
1052 QFETCH(QString, method);
1053 QFETCH(QString, createdName);
1055 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1056 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1057 QVERIFY(object != 0);
1059 QMetaObject::invokeMethod(object, method.toUtf8());
1060 QObject *created = object->objectProperty();
1062 QCOMPARE(created->objectName(), createdName);
1068 Tests the destroy function
1070 void tst_qdeclarativeecmascript::dynamicDestruction()
1072 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1073 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1074 QVERIFY(object != 0);
1075 QDeclarativeGuard<QObject> createdQmlObject = 0;
1077 QMetaObject::invokeMethod(object, "create");
1078 createdQmlObject = object->objectProperty();
1079 QVERIFY(createdQmlObject);
1080 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1082 QMetaObject::invokeMethod(object, "killOther");
1083 QVERIFY(createdQmlObject);
1084 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1085 QVERIFY(createdQmlObject);
1086 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1087 if (createdQmlObject) {
1089 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1092 QVERIFY(!createdQmlObject);
1094 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1095 QMetaObject::invokeMethod(object, "killMe");
1098 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1103 tests that id.toString() works
1105 void tst_qdeclarativeecmascript::objectToString()
1107 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1108 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1109 QVERIFY(object != 0);
1110 QMetaObject::invokeMethod(object, "testToString");
1111 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1112 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1118 Tests bindings that indirectly cause their own deletion work.
1120 This test is best run under valgrind to ensure no invalid memory access occur.
1122 void tst_qdeclarativeecmascript::selfDeletingBinding()
1125 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1126 QObject *object = component.create();
1127 QVERIFY(object != 0);
1128 object->setProperty("triggerDelete", true);
1133 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1134 QObject *object = component.create();
1135 QVERIFY(object != 0);
1136 object->setProperty("triggerDelete", true);
1142 Test that extended object properties can be accessed.
1144 This test a regression where this used to crash. The issue was specificially
1145 for extended objects that did not include a synthesized meta object (so non-root
1146 and no synthesiszed properties).
1148 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1150 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1151 QObject *object = component.create();
1152 QVERIFY(object != 0);
1157 Test file/lineNumbers for binding/Script errors.
1159 void tst_qdeclarativeecmascript::scriptErrors()
1161 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1162 QString url = component.url().toString();
1164 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1165 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1166 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1167 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1168 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1169 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1170 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1171 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1173 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1174 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1175 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1176 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1177 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1178 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1179 QVERIFY(object != 0);
1181 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1182 emit object->basicSignal();
1184 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1185 emit object->anotherBasicSignal();
1187 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1188 emit object->thirdBasicSignal();
1194 Test file/lineNumbers for inline functions.
1196 void tst_qdeclarativeecmascript::functionErrors()
1198 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1199 QString url = component.url().toString();
1201 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1203 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1205 QObject *object = component.create();
1206 QVERIFY(object != 0);
1209 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1210 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1211 url = componentTwo.url().toString();
1212 object = componentTwo.create();
1213 QVERIFY(object != 0);
1215 QString srpname = object->property("srp_name").toString();
1217 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1218 QLatin1String(" is not a function");
1219 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1220 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1225 Test various errors that can occur when assigning a property from script
1227 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1229 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1231 QString url = component.url().toString();
1233 QObject *object = component.create();
1234 QVERIFY(object != 0);
1236 QCOMPARE(object->property("test1").toBool(), true);
1237 QCOMPARE(object->property("test2").toBool(), true);
1243 Test bindings still work when the reeval is triggered from within
1246 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1248 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1249 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1250 QVERIFY(object != 0);
1252 QCOMPARE(object->property("base").toReal(), 50.);
1253 QCOMPARE(object->property("test1").toReal(), 50.);
1254 QCOMPARE(object->property("test2").toReal(), 50.);
1256 object->basicSignal();
1258 QCOMPARE(object->property("base").toReal(), 200.);
1259 QCOMPARE(object->property("test1").toReal(), 200.);
1260 QCOMPARE(object->property("test2").toReal(), 200.);
1262 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1264 QCOMPARE(object->property("base").toReal(), 400.);
1265 QCOMPARE(object->property("test1").toReal(), 400.);
1266 QCOMPARE(object->property("test2").toReal(), 400.);
1272 Test that list properties can be iterated from ECMAScript
1274 void tst_qdeclarativeecmascript::listProperties()
1276 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1277 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1278 QVERIFY(object != 0);
1280 QCOMPARE(object->property("test1").toInt(), 21);
1281 QCOMPARE(object->property("test2").toInt(), 2);
1282 QCOMPARE(object->property("test3").toBool(), true);
1283 QCOMPARE(object->property("test4").toBool(), true);
1288 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1290 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1291 QString url = component.url().toString();
1293 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1295 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1296 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1297 QVERIFY(object != 0);
1299 QCOMPARE(object->property("test").toBool(), false);
1301 MyQmlObject object2;
1302 MyQmlObject object3;
1303 object2.setObjectProperty(&object3);
1304 object->setObjectProperty(&object2);
1306 QCOMPARE(object->property("test").toBool(), true);
1311 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1313 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1314 QString url = component.url().toString();
1316 QString warning = component.url().toString() + ":6: Error: JS exception";
1318 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1319 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1320 QVERIFY(object != 0);
1324 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1326 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1327 QString url = component.url().toString();
1329 QString warning = component.url().toString() + ":5: Error: JS exception";
1331 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1332 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1333 QVERIFY(object != 0);
1337 static int transientErrorsMsgCount = 0;
1338 static void transientErrorsMsgHandler(QtMsgType, const char *)
1340 ++transientErrorsMsgCount;
1343 // Check that transient binding errors are not displayed
1344 void tst_qdeclarativeecmascript::transientErrors()
1347 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1349 transientErrorsMsgCount = 0;
1350 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1352 QObject *object = component.create();
1353 QVERIFY(object != 0);
1355 qInstallMsgHandler(old);
1357 QCOMPARE(transientErrorsMsgCount, 0);
1362 // One binding erroring multiple times, but then resolving
1364 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1366 transientErrorsMsgCount = 0;
1367 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1369 QObject *object = component.create();
1370 QVERIFY(object != 0);
1372 qInstallMsgHandler(old);
1374 QCOMPARE(transientErrorsMsgCount, 0);
1380 // Check that errors during shutdown are minimized
1381 void tst_qdeclarativeecmascript::shutdownErrors()
1383 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1384 QObject *object = component.create();
1385 QVERIFY(object != 0);
1387 transientErrorsMsgCount = 0;
1388 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1392 qInstallMsgHandler(old);
1393 QCOMPARE(transientErrorsMsgCount, 0);
1396 void tst_qdeclarativeecmascript::compositePropertyType()
1398 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1399 QTest::ignoreMessage(QtDebugMsg, "hello world");
1400 QObject *object = qobject_cast<QObject *>(component.create());
1405 void tst_qdeclarativeecmascript::jsObject()
1407 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1408 QObject *object = component.create();
1409 QVERIFY(object != 0);
1411 QCOMPARE(object->property("test").toInt(), 92);
1416 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1419 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1420 QObject *object = component.create();
1421 QVERIFY(object != 0);
1423 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1425 object->setProperty("setUndefined", true);
1427 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1429 object->setProperty("setUndefined", false);
1431 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1436 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1437 QObject *object = component.create();
1438 QVERIFY(object != 0);
1440 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1442 QMetaObject::invokeMethod(object, "doReset");
1444 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1451 void tst_qdeclarativeecmascript::bug1()
1453 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1454 QObject *object = component.create();
1455 QVERIFY(object != 0);
1457 QCOMPARE(object->property("test").toInt(), 14);
1459 object->setProperty("a", 11);
1461 QCOMPARE(object->property("test").toInt(), 3);
1463 object->setProperty("b", true);
1465 QCOMPARE(object->property("test").toInt(), 9);
1470 void tst_qdeclarativeecmascript::bug2()
1472 QDeclarativeComponent component(&engine);
1473 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1475 QObject *object = component.create();
1476 QVERIFY(object != 0);
1481 // Don't crash in createObject when the component has errors.
1482 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1484 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1485 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1486 QVERIFY(object != 0);
1488 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1489 QMetaObject::invokeMethod(object, "dontCrash");
1490 QObject *created = object->objectProperty();
1491 QVERIFY(created == 0);
1497 void tst_qdeclarativeecmascript::regExpBug()
1499 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1500 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1501 QVERIFY(object != 0);
1502 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1506 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1508 QString functionSource = QLatin1String("(function(object) { return ") +
1509 QLatin1String(source) + QLatin1String(" })");
1511 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1514 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1515 if (function.IsEmpty())
1517 v8::Handle<v8::Value> args[] = { o };
1518 function->Call(engine->global(), 1, args);
1519 return tc.HasCaught();
1522 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1523 const char *source, v8::Handle<v8::Value> result)
1525 QString functionSource = QLatin1String("(function(object) { return ") +
1526 QLatin1String(source) + QLatin1String(" })");
1528 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1531 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1532 if (function.IsEmpty())
1534 v8::Handle<v8::Value> args[] = { o };
1536 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1541 return value->StrictEquals(result);
1544 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1547 QString functionSource = QLatin1String("(function(object) { return ") +
1548 QLatin1String(source) + QLatin1String(" })");
1550 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1552 return v8::Handle<v8::Value>();
1553 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1554 if (function.IsEmpty())
1555 return v8::Handle<v8::Value>();
1556 v8::Handle<v8::Value> args[] = { o };
1558 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1561 return v8::Handle<v8::Value>();
1565 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1566 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1567 #define EVALUATE(source) evaluate(engine, object, source)
1569 void tst_qdeclarativeecmascript::callQtInvokables()
1571 MyInvokableObject o;
1573 QDeclarativeEngine qmlengine;
1574 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1576 QV8Engine *engine = &ep->v8engine;
1578 v8::HandleScope handle_scope;
1579 v8::Context::Scope scope(engine->context());
1581 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1583 // Non-existent methods
1585 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1586 QCOMPARE(o.error(), false);
1587 QCOMPARE(o.invoked(), -1);
1588 QCOMPARE(o.actuals().count(), 0);
1591 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1592 QCOMPARE(o.error(), false);
1593 QCOMPARE(o.invoked(), -1);
1594 QCOMPARE(o.actuals().count(), 0);
1596 // Insufficient arguments
1598 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1599 QCOMPARE(o.error(), false);
1600 QCOMPARE(o.invoked(), -1);
1601 QCOMPARE(o.actuals().count(), 0);
1604 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1605 QCOMPARE(o.error(), false);
1606 QCOMPARE(o.invoked(), -1);
1607 QCOMPARE(o.actuals().count(), 0);
1609 // Excessive arguments
1611 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1612 QCOMPARE(o.error(), false);
1613 QCOMPARE(o.invoked(), 8);
1614 QCOMPARE(o.actuals().count(), 1);
1615 QCOMPARE(o.actuals().at(0), QVariant(10));
1618 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1619 QCOMPARE(o.error(), false);
1620 QCOMPARE(o.invoked(), 9);
1621 QCOMPARE(o.actuals().count(), 2);
1622 QCOMPARE(o.actuals().at(0), QVariant(10));
1623 QCOMPARE(o.actuals().at(1), QVariant(11));
1625 // Test return types
1627 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1628 QCOMPARE(o.error(), false);
1629 QCOMPARE(o.invoked(), 0);
1630 QCOMPARE(o.actuals().count(), 0);
1633 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1634 QCOMPARE(o.error(), false);
1635 QCOMPARE(o.invoked(), 1);
1636 QCOMPARE(o.actuals().count(), 0);
1639 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1640 QCOMPARE(o.error(), false);
1641 QCOMPARE(o.invoked(), 2);
1642 QCOMPARE(o.actuals().count(), 0);
1646 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1647 QVERIFY(!ret.IsEmpty());
1648 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1649 QCOMPARE(o.error(), false);
1650 QCOMPARE(o.invoked(), 3);
1651 QCOMPARE(o.actuals().count(), 0);
1656 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1657 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1658 QCOMPARE(o.error(), false);
1659 QCOMPARE(o.invoked(), 4);
1660 QCOMPARE(o.actuals().count(), 0);
1664 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1665 QCOMPARE(o.error(), false);
1666 QCOMPARE(o.invoked(), 5);
1667 QCOMPARE(o.actuals().count(), 0);
1669 // XXX enable once qml/qtscript integration is implemented
1673 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1674 QVERIFY(ret->IsString());
1675 QCOMPARE(engine->toString(ret), QString("Hello world"));
1676 QCOMPARE(o.error(), false);
1677 QCOMPARE(o.invoked(), 6);
1678 QCOMPARE(o.actuals().count(), 0);
1683 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1684 QCOMPARE(o.error(), false);
1685 QCOMPARE(o.invoked(), 7);
1686 QCOMPARE(o.actuals().count(), 0);
1690 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1691 QCOMPARE(o.error(), false);
1692 QCOMPARE(o.invoked(), 8);
1693 QCOMPARE(o.actuals().count(), 1);
1694 QCOMPARE(o.actuals().at(0), QVariant(94));
1697 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1698 QCOMPARE(o.error(), false);
1699 QCOMPARE(o.invoked(), 8);
1700 QCOMPARE(o.actuals().count(), 1);
1701 QCOMPARE(o.actuals().at(0), QVariant(94));
1704 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1705 QCOMPARE(o.error(), false);
1706 QCOMPARE(o.invoked(), 8);
1707 QCOMPARE(o.actuals().count(), 1);
1708 QCOMPARE(o.actuals().at(0), QVariant(0));
1711 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1712 QCOMPARE(o.error(), false);
1713 QCOMPARE(o.invoked(), 8);
1714 QCOMPARE(o.actuals().count(), 1);
1715 QCOMPARE(o.actuals().at(0), QVariant(0));
1718 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1719 QCOMPARE(o.error(), false);
1720 QCOMPARE(o.invoked(), 8);
1721 QCOMPARE(o.actuals().count(), 1);
1722 QCOMPARE(o.actuals().at(0), QVariant(0));
1725 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1726 QCOMPARE(o.error(), false);
1727 QCOMPARE(o.invoked(), 8);
1728 QCOMPARE(o.actuals().count(), 1);
1729 QCOMPARE(o.actuals().at(0), QVariant(0));
1732 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1733 QCOMPARE(o.error(), false);
1734 QCOMPARE(o.invoked(), 9);
1735 QCOMPARE(o.actuals().count(), 2);
1736 QCOMPARE(o.actuals().at(0), QVariant(122));
1737 QCOMPARE(o.actuals().at(1), QVariant(9));
1740 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1741 QCOMPARE(o.error(), false);
1742 QCOMPARE(o.invoked(), 10);
1743 QCOMPARE(o.actuals().count(), 1);
1744 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1747 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1748 QCOMPARE(o.error(), false);
1749 QCOMPARE(o.invoked(), 10);
1750 QCOMPARE(o.actuals().count(), 1);
1751 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1754 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1755 QCOMPARE(o.error(), false);
1756 QCOMPARE(o.invoked(), 10);
1757 QCOMPARE(o.actuals().count(), 1);
1758 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1761 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1762 QCOMPARE(o.error(), false);
1763 QCOMPARE(o.invoked(), 10);
1764 QCOMPARE(o.actuals().count(), 1);
1765 QCOMPARE(o.actuals().at(0), QVariant(0));
1768 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1769 QCOMPARE(o.error(), false);
1770 QCOMPARE(o.invoked(), 10);
1771 QCOMPARE(o.actuals().count(), 1);
1772 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1775 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1776 QCOMPARE(o.error(), false);
1777 QCOMPARE(o.invoked(), 10);
1778 QCOMPARE(o.actuals().count(), 1);
1779 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1782 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1783 QCOMPARE(o.error(), false);
1784 QCOMPARE(o.invoked(), 11);
1785 QCOMPARE(o.actuals().count(), 1);
1786 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1789 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1790 QCOMPARE(o.error(), false);
1791 QCOMPARE(o.invoked(), 11);
1792 QCOMPARE(o.actuals().count(), 1);
1793 QCOMPARE(o.actuals().at(0), QVariant("19"));
1797 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1798 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1799 QCOMPARE(o.error(), false);
1800 QCOMPARE(o.invoked(), 11);
1801 QCOMPARE(o.actuals().count(), 1);
1802 QCOMPARE(o.actuals().at(0), QVariant(expected));
1806 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1807 QCOMPARE(o.error(), false);
1808 QCOMPARE(o.invoked(), 11);
1809 QCOMPARE(o.actuals().count(), 1);
1810 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1813 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1814 QCOMPARE(o.error(), false);
1815 QCOMPARE(o.invoked(), 11);
1816 QCOMPARE(o.actuals().count(), 1);
1817 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1820 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1821 QCOMPARE(o.error(), false);
1822 QCOMPARE(o.invoked(), 12);
1823 QCOMPARE(o.actuals().count(), 1);
1824 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1827 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1828 QCOMPARE(o.error(), false);
1829 QCOMPARE(o.invoked(), 12);
1830 QCOMPARE(o.actuals().count(), 1);
1831 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1834 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1835 QCOMPARE(o.error(), false);
1836 QCOMPARE(o.invoked(), 12);
1837 QCOMPARE(o.actuals().count(), 1);
1838 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1841 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1842 QCOMPARE(o.error(), false);
1843 QCOMPARE(o.invoked(), 12);
1844 QCOMPARE(o.actuals().count(), 1);
1845 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1848 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
1849 QCOMPARE(o.error(), false);
1850 QCOMPARE(o.invoked(), 12);
1851 QCOMPARE(o.actuals().count(), 1);
1852 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1855 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
1856 QCOMPARE(o.error(), false);
1857 QCOMPARE(o.invoked(), 12);
1858 QCOMPARE(o.actuals().count(), 1);
1859 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1862 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
1863 QCOMPARE(o.error(), false);
1864 QCOMPARE(o.invoked(), 13);
1865 QCOMPARE(o.actuals().count(), 1);
1866 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1869 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
1870 QCOMPARE(o.error(), false);
1871 QCOMPARE(o.invoked(), 13);
1872 QCOMPARE(o.actuals().count(), 1);
1873 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1876 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
1877 QCOMPARE(o.error(), false);
1878 QCOMPARE(o.invoked(), 13);
1879 QCOMPARE(o.actuals().count(), 1);
1880 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1883 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
1884 QCOMPARE(o.error(), false);
1885 QCOMPARE(o.invoked(), 13);
1886 QCOMPARE(o.actuals().count(), 1);
1887 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1890 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
1891 QCOMPARE(o.error(), false);
1892 QCOMPARE(o.invoked(), 13);
1893 QCOMPARE(o.actuals().count(), 1);
1894 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1896 // XXX enable once qml/qtscript integration is implemented
1899 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
1900 QCOMPARE(o.error(), false);
1901 QCOMPARE(o.invoked(), 14);
1902 QCOMPARE(o.actuals().count(), 1);
1903 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1906 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
1907 QCOMPARE(o.error(), false);
1908 QCOMPARE(o.invoked(), 14);
1909 QCOMPARE(o.actuals().count(), 1);
1910 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1913 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
1914 QCOMPARE(o.error(), false);
1915 QCOMPARE(o.invoked(), 14);
1916 QCOMPARE(o.actuals().count(), 1);
1917 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1920 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
1921 QCOMPARE(o.error(), false);
1922 QCOMPARE(o.invoked(), 14);
1923 QCOMPARE(o.actuals().count(), 1);
1924 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1927 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
1928 QCOMPARE(o.error(), false);
1929 QCOMPARE(o.invoked(), 15);
1930 QCOMPARE(o.actuals().count(), 2);
1931 QCOMPARE(o.actuals().at(0), QVariant(4));
1932 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1935 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
1936 QCOMPARE(o.error(), false);
1937 QCOMPARE(o.invoked(), 15);
1938 QCOMPARE(o.actuals().count(), 2);
1939 QCOMPARE(o.actuals().at(0), QVariant(8));
1940 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1943 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
1944 QCOMPARE(o.error(), false);
1945 QCOMPARE(o.invoked(), 15);
1946 QCOMPARE(o.actuals().count(), 2);
1947 QCOMPARE(o.actuals().at(0), QVariant(3));
1948 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1951 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
1952 QCOMPARE(o.error(), false);
1953 QCOMPARE(o.invoked(), 15);
1954 QCOMPARE(o.actuals().count(), 2);
1955 QCOMPARE(o.actuals().at(0), QVariant(44));
1956 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1960 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
1961 QCOMPARE(o.error(), false);
1962 QCOMPARE(o.invoked(), -1);
1963 QCOMPARE(o.actuals().count(), 0);
1966 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
1967 QCOMPARE(o.error(), false);
1968 QCOMPARE(o.invoked(), 16);
1969 QCOMPARE(o.actuals().count(), 1);
1970 QCOMPARE(o.actuals().at(0), QVariant(10));
1973 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
1974 QCOMPARE(o.error(), false);
1975 QCOMPARE(o.invoked(), 17);
1976 QCOMPARE(o.actuals().count(), 2);
1977 QCOMPARE(o.actuals().at(0), QVariant(10));
1978 QCOMPARE(o.actuals().at(1), QVariant(11));
1981 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
1982 QCOMPARE(o.error(), false);
1983 QCOMPARE(o.invoked(), 18);
1984 QCOMPARE(o.actuals().count(), 1);
1985 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1988 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
1989 QCOMPARE(o.error(), false);
1990 QCOMPARE(o.invoked(), 19);
1991 QCOMPARE(o.actuals().count(), 1);
1992 QCOMPARE(o.actuals().at(0), QVariant(9));
1995 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
1996 QCOMPARE(o.error(), false);
1997 QCOMPARE(o.invoked(), 20);
1998 QCOMPARE(o.actuals().count(), 2);
1999 QCOMPARE(o.actuals().at(0), QVariant(10));
2000 QCOMPARE(o.actuals().at(1), QVariant(19));
2003 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2004 QCOMPARE(o.error(), false);
2005 QCOMPARE(o.invoked(), 20);
2006 QCOMPARE(o.actuals().count(), 2);
2007 QCOMPARE(o.actuals().at(0), QVariant(10));
2008 QCOMPARE(o.actuals().at(1), QVariant(13));
2011 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2012 QCOMPARE(o.error(), false);
2013 QCOMPARE(o.invoked(), -3);
2014 QCOMPARE(o.actuals().count(), 1);
2015 QCOMPARE(o.actuals().at(0), QVariant(9));
2018 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2019 QCOMPARE(o.error(), false);
2020 QCOMPARE(o.invoked(), 21);
2021 QCOMPARE(o.actuals().count(), 2);
2022 QCOMPARE(o.actuals().at(0), QVariant(9));
2023 QCOMPARE(o.actuals().at(1), QVariant());
2026 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2027 QCOMPARE(o.error(), false);
2028 QCOMPARE(o.invoked(), 21);
2029 QCOMPARE(o.actuals().count(), 2);
2030 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2031 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2034 // QTBUG-13047 (check that you can pass registered object types as args)
2035 void tst_qdeclarativeecmascript::invokableObjectArg()
2037 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2039 QObject *o = component.create();
2041 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2043 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2048 // QTBUG-13047 (check that you can return registered object types from methods)
2049 void tst_qdeclarativeecmascript::invokableObjectRet()
2051 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2053 QObject *o = component.create();
2055 QCOMPARE(o->property("test").toBool(), true);
2060 void tst_qdeclarativeecmascript::listToVariant()
2062 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2064 MyQmlContainer container;
2066 QDeclarativeContext context(engine.rootContext());
2067 context.setContextObject(&container);
2069 QObject *object = component.create(&context);
2070 QVERIFY(object != 0);
2072 QVariant v = object->property("test");
2073 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2074 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2080 void tst_qdeclarativeecmascript::multiEngineObject()
2083 obj.setStringProperty("Howdy planet");
2085 QDeclarativeEngine e1;
2086 e1.rootContext()->setContextProperty("thing", &obj);
2087 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2089 QDeclarativeEngine e2;
2090 e2.rootContext()->setContextProperty("thing", &obj);
2091 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2093 QObject *o1 = c1.create();
2094 QObject *o2 = c2.create();
2096 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2097 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2103 // Test that references to QObjects are cleanup when the object is destroyed
2104 void tst_qdeclarativeecmascript::deletedObject()
2106 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2108 QObject *object = component.create();
2110 QCOMPARE(object->property("test1").toBool(), true);
2111 QCOMPARE(object->property("test2").toBool(), true);
2112 QCOMPARE(object->property("test3").toBool(), true);
2113 QCOMPARE(object->property("test4").toBool(), true);
2118 void tst_qdeclarativeecmascript::attachedPropertyScope()
2120 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2122 QObject *object = component.create();
2123 QVERIFY(object != 0);
2125 MyQmlAttachedObject *attached =
2126 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2127 QVERIFY(attached != 0);
2129 QCOMPARE(object->property("value2").toInt(), 0);
2131 attached->emitMySignal();
2133 QCOMPARE(object->property("value2").toInt(), 9);
2138 void tst_qdeclarativeecmascript::scriptConnect()
2141 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2143 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2144 QVERIFY(object != 0);
2146 QCOMPARE(object->property("test").toBool(), false);
2147 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2148 QCOMPARE(object->property("test").toBool(), true);
2154 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2156 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2157 QVERIFY(object != 0);
2159 QCOMPARE(object->property("test").toBool(), false);
2160 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2161 QCOMPARE(object->property("test").toBool(), true);
2167 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2169 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2170 QVERIFY(object != 0);
2172 QCOMPARE(object->property("test").toBool(), false);
2173 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2174 QCOMPARE(object->property("test").toBool(), true);
2180 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2182 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2183 QVERIFY(object != 0);
2185 QCOMPARE(object->methodCalled(), false);
2186 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2187 QCOMPARE(object->methodCalled(), true);
2193 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2195 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2196 QVERIFY(object != 0);
2198 QCOMPARE(object->methodCalled(), false);
2199 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2200 QCOMPARE(object->methodCalled(), true);
2206 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2208 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2209 QVERIFY(object != 0);
2211 QCOMPARE(object->property("test").toInt(), 0);
2212 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2213 QCOMPARE(object->property("test").toInt(), 2);
2219 void tst_qdeclarativeecmascript::scriptDisconnect()
2222 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2224 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2225 QVERIFY(object != 0);
2227 QCOMPARE(object->property("test").toInt(), 0);
2228 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2229 QCOMPARE(object->property("test").toInt(), 1);
2230 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2231 QCOMPARE(object->property("test").toInt(), 2);
2232 emit object->basicSignal();
2233 QCOMPARE(object->property("test").toInt(), 2);
2234 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2235 QCOMPARE(object->property("test").toInt(), 2);
2241 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2243 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2244 QVERIFY(object != 0);
2246 QCOMPARE(object->property("test").toInt(), 0);
2247 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2248 QCOMPARE(object->property("test").toInt(), 1);
2249 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2250 QCOMPARE(object->property("test").toInt(), 2);
2251 emit object->basicSignal();
2252 QCOMPARE(object->property("test").toInt(), 2);
2253 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2254 QCOMPARE(object->property("test").toInt(), 2);
2260 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2262 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2263 QVERIFY(object != 0);
2265 QCOMPARE(object->property("test").toInt(), 0);
2266 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2267 QCOMPARE(object->property("test").toInt(), 1);
2268 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2269 QCOMPARE(object->property("test").toInt(), 2);
2270 emit object->basicSignal();
2271 QCOMPARE(object->property("test").toInt(), 2);
2272 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2273 QCOMPARE(object->property("test").toInt(), 3);
2278 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2280 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2281 QVERIFY(object != 0);
2283 QCOMPARE(object->property("test").toInt(), 0);
2284 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2285 QCOMPARE(object->property("test").toInt(), 1);
2286 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2287 QCOMPARE(object->property("test").toInt(), 2);
2288 emit object->basicSignal();
2289 QCOMPARE(object->property("test").toInt(), 2);
2290 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2291 QCOMPARE(object->property("test").toInt(), 3);
2297 class OwnershipObject : public QObject
2301 OwnershipObject() { object = new QObject; }
2303 QPointer<QObject> object;
2306 QObject *getObject() { return object; }
2309 void tst_qdeclarativeecmascript::ownership()
2311 OwnershipObject own;
2312 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2313 context->setContextObject(&own);
2316 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2318 QVERIFY(own.object != 0);
2320 QObject *object = component.create(context);
2322 engine.collectGarbage();
2324 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2326 QVERIFY(own.object == 0);
2331 own.object = new QObject(&own);
2334 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2336 QVERIFY(own.object != 0);
2338 QObject *object = component.create(context);
2340 engine.collectGarbage();
2342 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2344 QVERIFY(own.object != 0);
2352 class CppOwnershipReturnValue : public QObject
2356 CppOwnershipReturnValue() : value(0) {}
2357 ~CppOwnershipReturnValue() { delete value; }
2359 Q_INVOKABLE QObject *create() {
2360 value = new QObject;
2361 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2365 Q_INVOKABLE MyQmlObject *createQmlObject() {
2366 MyQmlObject *rv = new MyQmlObject;
2371 QPointer<QObject> value;
2375 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2376 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2378 CppOwnershipReturnValue source;
2381 QDeclarativeEngine engine;
2382 engine.rootContext()->setContextProperty("source", &source);
2384 QVERIFY(source.value == 0);
2386 QDeclarativeComponent component(&engine);
2387 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2389 QObject *object = component.create();
2391 QVERIFY(object != 0);
2392 QVERIFY(source.value != 0);
2397 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2399 QVERIFY(source.value != 0);
2403 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2405 CppOwnershipReturnValue source;
2408 QDeclarativeEngine engine;
2409 engine.rootContext()->setContextProperty("source", &source);
2411 QVERIFY(source.value == 0);
2413 QDeclarativeComponent component(&engine);
2414 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2416 QObject *object = component.create();
2418 QVERIFY(object != 0);
2419 QVERIFY(source.value != 0);
2424 engine.collectGarbage();
2425 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2427 QVERIFY(source.value == 0);
2430 class QListQObjectMethodsObject : public QObject
2434 QListQObjectMethodsObject() {
2435 m_objects.append(new MyQmlObject());
2436 m_objects.append(new MyQmlObject());
2439 ~QListQObjectMethodsObject() {
2440 qDeleteAll(m_objects);
2444 QList<QObject *> getObjects() { return m_objects; }
2447 QList<QObject *> m_objects;
2450 // Tests that returning a QList<QObject*> from a method works
2451 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2453 QListQObjectMethodsObject obj;
2454 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2455 context->setContextObject(&obj);
2457 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2459 QObject *object = component.create(context);
2461 QCOMPARE(object->property("test").toInt(), 2);
2462 QCOMPARE(object->property("test2").toBool(), true);
2469 void tst_qdeclarativeecmascript::strictlyEquals()
2471 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2473 QObject *object = component.create();
2474 QVERIFY(object != 0);
2476 QCOMPARE(object->property("test1").toBool(), true);
2477 QCOMPARE(object->property("test2").toBool(), true);
2478 QCOMPARE(object->property("test3").toBool(), true);
2479 QCOMPARE(object->property("test4").toBool(), true);
2480 QCOMPARE(object->property("test5").toBool(), true);
2481 QCOMPARE(object->property("test6").toBool(), true);
2482 QCOMPARE(object->property("test7").toBool(), true);
2483 QCOMPARE(object->property("test8").toBool(), true);
2488 void tst_qdeclarativeecmascript::compiled()
2490 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2492 QObject *object = component.create();
2493 QVERIFY(object != 0);
2495 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2496 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2497 QCOMPARE(object->property("test3").toBool(), true);
2498 QCOMPARE(object->property("test4").toBool(), false);
2499 QCOMPARE(object->property("test5").toBool(), false);
2500 QCOMPARE(object->property("test6").toBool(), true);
2502 QCOMPARE(object->property("test7").toInt(), 185);
2503 QCOMPARE(object->property("test8").toInt(), 167);
2504 QCOMPARE(object->property("test9").toBool(), true);
2505 QCOMPARE(object->property("test10").toBool(), false);
2506 QCOMPARE(object->property("test11").toBool(), false);
2507 QCOMPARE(object->property("test12").toBool(), true);
2509 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2510 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2511 QCOMPARE(object->property("test15").toBool(), false);
2512 QCOMPARE(object->property("test16").toBool(), true);
2514 QCOMPARE(object->property("test17").toInt(), 5);
2515 QCOMPARE(object->property("test18").toReal(), qreal(176));
2516 QCOMPARE(object->property("test19").toInt(), 7);
2517 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2518 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2519 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2520 QCOMPARE(object->property("test23").toBool(), true);
2521 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2522 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2527 // Test that numbers assigned in bindings as strings work consistently
2528 void tst_qdeclarativeecmascript::numberAssignment()
2530 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2532 QObject *object = component.create();
2533 QVERIFY(object != 0);
2535 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2536 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2537 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2538 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2539 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2541 QCOMPARE(object->property("test5"), QVariant((int)7));
2542 QCOMPARE(object->property("test6"), QVariant((int)7));
2543 QCOMPARE(object->property("test7"), QVariant((int)6));
2544 QCOMPARE(object->property("test8"), QVariant((int)6));
2546 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2547 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2548 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2549 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2554 void tst_qdeclarativeecmascript::propertySplicing()
2556 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2558 QObject *object = component.create();
2559 QVERIFY(object != 0);
2561 QCOMPARE(object->property("test").toBool(), true);
2567 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2569 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2571 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2572 QVERIFY(object != 0);
2574 MyQmlObject::MyType type;
2575 type.value = 0x8971123;
2576 emit object->signalWithUnknownType(type);
2578 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2580 QCOMPARE(result.value, type.value);
2586 void tst_qdeclarativeecmascript::moduleApi()
2588 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2589 QObject *object = component.create();
2590 QVERIFY(object != 0);
2591 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2593 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2594 QCOMPARE(object->property("scriptTest").toInt(), 13);
2595 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2596 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2597 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2598 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2599 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2602 // test that caching of module apis works correctly.
2603 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2604 object = componentTwo.create();
2605 QVERIFY(object != 0);
2606 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2607 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2608 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2609 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2612 // test that writing to a property of module apis works correctly.
2613 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2614 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2615 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2616 object = componentThree.create();
2617 QVERIFY(object != 0);
2618 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2619 QCOMPARE(object->property("writableProperty").toInt(), 50);
2620 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2621 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2622 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2623 QCOMPARE(object->property("writableProperty").toInt(), 30);
2626 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2627 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2628 object = failOne.create();
2629 QVERIFY(object == 0); // should have failed: invalid major version
2631 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2632 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2633 object = failTwo.create();
2634 QVERIFY(object == 0); // should have failed: invalid minor version
2637 void tst_qdeclarativeecmascript::importScripts()
2639 QObject *object = 0;
2641 // first, ensure that the required behaviour works.
2642 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2643 object = component.create();
2644 QVERIFY(object != 0);
2645 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2646 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2647 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2648 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2651 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2652 object = componentTwo.create();
2653 QVERIFY(object != 0);
2654 QCOMPARE(object->property("componentError"), QVariant(5));
2657 // then, ensure that unintended behaviour does not work.
2658 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2659 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2660 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2661 object = failOneComponent.create();
2662 QVERIFY(object != 0);
2663 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2665 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2666 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2667 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2668 object = failTwoComponent.create();
2669 QVERIFY(object != 0);
2670 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2672 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2673 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2674 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2675 object = failThreeComponent.create();
2676 QVERIFY(object != 0);
2677 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2679 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2680 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2681 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2682 object = failFourComponent.create();
2683 QVERIFY(object != 0);
2684 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2686 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2687 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2688 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2689 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2690 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2691 object = failFiveComponent.create();
2692 QVERIFY(object != 0);
2693 QCOMPARE(object->property("componentError"), QVariant(0));
2696 // also, test that importing scripts with .pragma library works as required
2697 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2698 object = pragmaLibraryComponent.create();
2699 QVERIFY(object != 0);
2700 QCOMPARE(object->property("testValue"), QVariant(31));
2703 // and that .pragma library scripts don't inherit imports from any .qml file
2704 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2705 object = pragmaLibraryComponentTwo.create();
2706 QVERIFY(object != 0);
2707 QCOMPARE(object->property("testValue"), QVariant(0));
2711 void tst_qdeclarativeecmascript::scarceResources()
2713 QPixmap origPixmap(100, 100);
2714 origPixmap.fill(Qt::blue);
2716 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2717 ScarceResourceObject *eo = 0;
2718 QObject *object = 0;
2720 // in the following three cases, the instance created from the component
2721 // has a property which is a copy of the scarce resource; hence, the
2722 // resource should NOT be detached prior to deletion of the object instance,
2723 // unless the resource is destroyed explicitly.
2724 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2725 object = component.create();
2726 QVERIFY(object != 0);
2727 QVERIFY(object->property("scarceResourceCopy").isValid());
2728 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2729 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2730 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2731 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2734 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2735 object = componentTwo.create();
2736 QVERIFY(object != 0);
2737 QVERIFY(object->property("scarceResourceCopy").isValid());
2738 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2739 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2740 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2741 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2744 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2745 object = componentThree.create();
2746 QVERIFY(object != 0);
2747 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2748 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2749 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2750 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2753 // in the following three cases, no other copy should exist in memory,
2754 // and so it should be detached (unless explicitly preserved).
2755 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2756 object = componentFour.create();
2757 QVERIFY(object != 0);
2758 QVERIFY(object->property("scarceResourceTest").isValid());
2759 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2760 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2761 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2762 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2765 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2766 object = componentFive.create();
2767 QVERIFY(object != 0);
2768 QVERIFY(object->property("scarceResourceTest").isValid());
2769 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2770 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2771 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2772 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2775 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2776 object = componentSix.create();
2777 QVERIFY(object != 0);
2778 QVERIFY(object->property("scarceResourceTest").isValid());
2779 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2780 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2781 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2782 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2785 // test that scarce resources are handled correctly for imports
2786 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2787 object = componentSeven.create();
2788 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2789 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
2792 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2793 object = componentEight.create();
2794 QVERIFY(object != 0);
2795 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2796 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2799 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2800 object = componentNine.create();
2801 QVERIFY(object != 0);
2802 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2803 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2804 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2805 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2806 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2807 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
2810 // test that scarce resources are handled properly in signal invocation
2811 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2812 object = componentTen.create();
2813 QVERIFY(object != 0);
2814 QObject *srsc = object->findChild<QObject*>("srsc");
2816 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2817 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2818 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2819 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2820 QMetaObject::invokeMethod(srsc, "testSignal");
2821 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2822 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2823 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2824 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2825 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2826 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2827 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2828 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2829 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2830 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2833 // test that scarce resources are handled properly from js functions in qml files
2834 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2835 object = componentEleven.create();
2836 QVERIFY(object != 0);
2837 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2838 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2839 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2840 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2841 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2842 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2843 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2844 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2845 QMetaObject::invokeMethod(object, "releaseScarceResource");
2846 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2847 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2848 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2849 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2852 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2853 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2854 object = componentTwelve.create();
2855 QVERIFY(object != 0);
2856 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2857 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2858 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2859 QString srp_name = object->property("srp_name").toString();
2860 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
2861 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
2862 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2863 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2864 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2865 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2866 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2870 void tst_qdeclarativeecmascript::propertyChangeSlots()
2872 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2873 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2874 QObject *object = component.create();
2875 QVERIFY(object != 0);
2878 // ensure that invalid property names fail properly.
2879 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2880 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2881 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2882 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2883 object = e1.create();
2884 QVERIFY(object == 0);
2887 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2888 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2889 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2890 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2891 object = e2.create();
2892 QVERIFY(object == 0);
2895 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2896 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2897 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2898 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2899 object = e3.create();
2900 QVERIFY(object == 0);
2903 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2904 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2905 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2906 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2907 object = e4.create();
2908 QVERIFY(object == 0);
2912 // Test that assigning a null object works
2913 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2914 void tst_qdeclarativeecmascript::nullObjectBinding()
2916 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2918 QObject *object = component.create();
2919 QVERIFY(object != 0);
2921 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2926 // Test that bindings don't evaluate once the engine has been destroyed
2927 void tst_qdeclarativeecmascript::deletedEngine()
2929 QDeclarativeEngine *engine = new QDeclarativeEngine;
2930 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2932 QObject *object = component.create();
2933 QVERIFY(object != 0);
2935 QCOMPARE(object->property("a").toInt(), 39);
2936 object->setProperty("b", QVariant(9));
2937 QCOMPARE(object->property("a").toInt(), 117);
2941 QCOMPARE(object->property("a").toInt(), 117);
2942 object->setProperty("b", QVariant(10));
2943 QCOMPARE(object->property("a").toInt(), 117);
2948 // Test the crashing part of QTBUG-9705
2949 void tst_qdeclarativeecmascript::libraryScriptAssert()
2951 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2953 QObject *object = component.create();
2954 QVERIFY(object != 0);
2959 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2961 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2963 QObject *object = component.create();
2964 QVERIFY(object != 0);
2966 QCOMPARE(object->property("test1").toInt(), 10);
2967 QCOMPARE(object->property("test2").toInt(), 11);
2969 object->setProperty("runTest", true);
2971 QCOMPARE(object->property("test1"), QVariant());
2972 QCOMPARE(object->property("test2"), QVariant());
2978 void tst_qdeclarativeecmascript::qtbug_9792()
2980 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
2982 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2984 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
2985 QVERIFY(object != 0);
2987 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
2988 object->basicSignal();
2992 transientErrorsMsgCount = 0;
2993 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2995 object->basicSignal();
2997 qInstallMsgHandler(old);
2999 QCOMPARE(transientErrorsMsgCount, 0);
3004 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3005 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3007 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3009 QObject *o = component.create();
3012 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3013 QVERIFY(nested != 0);
3015 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3018 nested = qvariant_cast<QObject *>(o->property("object"));
3019 QVERIFY(nested == 0);
3021 // If the bug is present, the next line will crash
3025 // Test that we shut down without stupid warnings
3026 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3029 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3031 QObject *o = component.create();
3033 transientErrorsMsgCount = 0;
3034 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3038 qInstallMsgHandler(old);
3040 QCOMPARE(transientErrorsMsgCount, 0);
3045 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3047 QObject *o = component.create();
3049 transientErrorsMsgCount = 0;
3050 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3054 qInstallMsgHandler(old);
3056 QCOMPARE(transientErrorsMsgCount, 0);
3060 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3063 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3065 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3068 QVERIFY(o->objectProperty() != 0);
3070 o->setProperty("runTest", true);
3072 QVERIFY(o->objectProperty() == 0);
3078 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3080 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3083 QVERIFY(o->objectProperty() == 0);
3089 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3091 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3093 QString url = component.url().toString();
3094 QString warning = url + ":4: Unable to assign a function to a property.";
3095 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3097 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3100 QVERIFY(!o->property("a").isValid());
3105 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3107 QFETCH(QString, triggerProperty);
3109 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3110 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3112 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3114 QVERIFY(!o->property("a").isValid());
3116 o->setProperty("aNumber", QVariant(5));
3117 o->setProperty(triggerProperty.toUtf8().constData(), true);
3118 QCOMPARE(o->property("a"), QVariant(50));
3120 o->setProperty("aNumber", QVariant(10));
3121 QCOMPARE(o->property("a"), QVariant(100));
3126 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3128 QTest::addColumn<QString>("triggerProperty");
3130 QTest::newRow("assign to property") << "assignToProperty";
3131 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3133 QTest::newRow("assign to value type") << "assignToValueType";
3135 QTest::newRow("use 'this'") << "assignWithThis";
3136 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3139 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3141 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3142 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3144 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3146 QVERIFY(!o->property("a").isValid());
3148 o->setProperty("assignFuncWithoutReturn", true);
3149 QVERIFY(!o->property("a").isValid());
3151 QString url = component.url().toString();
3152 QString warning = url + ":67: Unable to assign QString to int";
3153 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3154 o->setProperty("assignWrongType", true);
3156 warning = url + ":71: Unable to assign QString to int";
3157 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3158 o->setProperty("assignWrongTypeToValueType", true);
3163 void tst_qdeclarativeecmascript::eval()
3165 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3167 QObject *o = component.create();
3170 QCOMPARE(o->property("test1").toBool(), true);
3171 QCOMPARE(o->property("test2").toBool(), true);
3172 QCOMPARE(o->property("test3").toBool(), true);
3173 QCOMPARE(o->property("test4").toBool(), true);
3174 QCOMPARE(o->property("test5").toBool(), true);
3179 void tst_qdeclarativeecmascript::function()
3181 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3183 QObject *o = component.create();
3186 QCOMPARE(o->property("test1").toBool(), true);
3187 QCOMPARE(o->property("test2").toBool(), true);
3188 QCOMPARE(o->property("test3").toBool(), true);
3193 // Test the "Qt.include" method
3194 void tst_qdeclarativeecmascript::include()
3196 // Non-library relative include
3198 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3199 QObject *o = component.create();
3202 QCOMPARE(o->property("test0").toInt(), 99);
3203 QCOMPARE(o->property("test1").toBool(), true);
3204 QCOMPARE(o->property("test2").toBool(), true);
3205 QCOMPARE(o->property("test2_1").toBool(), true);
3206 QCOMPARE(o->property("test3").toBool(), true);
3207 QCOMPARE(o->property("test3_1").toBool(), true);
3212 // Library relative include
3214 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3215 QObject *o = component.create();
3218 QCOMPARE(o->property("test0").toInt(), 99);
3219 QCOMPARE(o->property("test1").toBool(), true);
3220 QCOMPARE(o->property("test2").toBool(), true);
3221 QCOMPARE(o->property("test2_1").toBool(), true);
3222 QCOMPARE(o->property("test3").toBool(), true);
3223 QCOMPARE(o->property("test3_1").toBool(), true);
3230 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3231 QObject *o = component.create();
3234 QCOMPARE(o->property("test1").toBool(), true);
3235 QCOMPARE(o->property("test2").toBool(), true);
3236 QCOMPARE(o->property("test3").toBool(), true);
3237 QCOMPARE(o->property("test4").toBool(), true);
3238 QCOMPARE(o->property("test5").toBool(), true);
3239 QCOMPARE(o->property("test6").toBool(), true);
3244 // Including file with ".pragma library"
3246 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3247 QObject *o = component.create();
3249 QCOMPARE(o->property("test1").toInt(), 100);
3256 TestHTTPServer server(8111);
3257 QVERIFY(server.isValid());
3258 server.serveDirectory(SRCDIR "/data");
3260 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3261 QObject *o = component.create();
3264 QTRY_VERIFY(o->property("done").toBool() == true);
3265 QTRY_VERIFY(o->property("done2").toBool() == true);
3267 QCOMPARE(o->property("test1").toBool(), true);
3268 QCOMPARE(o->property("test2").toBool(), true);
3269 QCOMPARE(o->property("test3").toBool(), true);
3270 QCOMPARE(o->property("test4").toBool(), true);
3271 QCOMPARE(o->property("test5").toBool(), true);
3273 QCOMPARE(o->property("test6").toBool(), true);
3274 QCOMPARE(o->property("test7").toBool(), true);
3275 QCOMPARE(o->property("test8").toBool(), true);
3276 QCOMPARE(o->property("test9").toBool(), true);
3277 QCOMPARE(o->property("test10").toBool(), true);
3284 TestHTTPServer server(8111);
3285 QVERIFY(server.isValid());
3286 server.serveDirectory(SRCDIR "/data");
3288 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3289 QObject *o = component.create();
3292 QTRY_VERIFY(o->property("done").toBool() == true);
3294 QCOMPARE(o->property("test1").toBool(), true);
3295 QCOMPARE(o->property("test2").toBool(), true);
3296 QCOMPARE(o->property("test3").toBool(), true);
3302 void tst_qdeclarativeecmascript::qtbug_10696()
3304 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3305 QObject *o = component.create();
3310 void tst_qdeclarativeecmascript::qtbug_11606()
3312 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3313 QObject *o = component.create();
3315 QCOMPARE(o->property("test").toBool(), true);
3319 void tst_qdeclarativeecmascript::qtbug_11600()
3321 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3322 QObject *o = component.create();
3324 QCOMPARE(o->property("test").toBool(), true);
3328 // Reading and writing non-scriptable properties should fail
3329 void tst_qdeclarativeecmascript::nonscriptable()
3331 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3332 QObject *o = component.create();
3334 QCOMPARE(o->property("readOk").toBool(), true);
3335 QCOMPARE(o->property("writeOk").toBool(), true);
3339 // deleteLater() should not be callable from QML
3340 void tst_qdeclarativeecmascript::deleteLater()
3342 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3343 QObject *o = component.create();
3345 QCOMPARE(o->property("test").toBool(), true);
3349 void tst_qdeclarativeecmascript::in()
3351 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3352 QObject *o = component.create();
3354 QCOMPARE(o->property("test1").toBool(), true);
3355 QCOMPARE(o->property("test2").toBool(), true);
3359 void tst_qdeclarativeecmascript::sharedAttachedObject()
3361 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3362 QObject *o = component.create();
3364 QCOMPARE(o->property("test1").toBool(), true);
3365 QCOMPARE(o->property("test2").toBool(), true);
3370 void tst_qdeclarativeecmascript::objectName()
3372 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3373 QObject *o = component.create();
3376 QCOMPARE(o->property("test1").toString(), QString("hello"));
3377 QCOMPARE(o->property("test2").toString(), QString("ell"));
3379 o->setObjectName("world");
3381 QCOMPARE(o->property("test1").toString(), QString("world"));
3382 QCOMPARE(o->property("test2").toString(), QString("orl"));
3387 void tst_qdeclarativeecmascript::writeRemovesBinding()
3389 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3390 QObject *o = component.create();
3393 QCOMPARE(o->property("test").toBool(), true);
3398 // Test bindings assigned to alias properties actually assign to the alias' target
3399 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3401 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3402 QObject *o = component.create();
3405 QCOMPARE(o->property("test").toBool(), true);
3410 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3411 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3414 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3415 QObject *o = component.create();
3418 QCOMPARE(o->property("test").toBool(), true);
3424 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3425 QObject *o = component.create();
3428 QCOMPARE(o->property("test").toBool(), true);
3434 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3435 QObject *o = component.create();
3438 QCOMPARE(o->property("test").toBool(), true);
3444 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3445 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3448 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3449 QObject *o = component.create();
3452 QCOMPARE(o->property("test").toBool(), true);
3458 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3459 QObject *o = component.create();
3462 QCOMPARE(o->property("test").toBool(), true);
3468 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3469 QObject *o = component.create();
3472 QCOMPARE(o->property("test").toBool(), true);
3478 void tst_qdeclarativeecmascript::revisionErrors()
3481 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3482 QString url = component.url().toString();
3484 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3485 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3486 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3488 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3489 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3490 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3491 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3492 QVERIFY(object != 0);
3496 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3497 QString url = component.url().toString();
3499 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3500 // method2, prop2 from MyRevisionedClass not available
3501 // method4, prop4 from MyRevisionedSubclass not available
3502 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3503 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3504 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3505 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3506 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3508 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3509 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3510 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3511 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3512 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3513 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3514 QVERIFY(object != 0);
3518 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3519 QString url = component.url().toString();
3521 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3522 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3523 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3524 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3525 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3526 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3527 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3528 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3529 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3530 QVERIFY(object != 0);
3535 void tst_qdeclarativeecmascript::revision()
3538 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3539 QString url = component.url().toString();
3541 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3542 QVERIFY(object != 0);
3546 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3547 QString url = component.url().toString();
3549 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3550 QVERIFY(object != 0);
3554 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3555 QString url = component.url().toString();
3557 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3558 QVERIFY(object != 0);
3561 // Test that non-root classes can resolve revisioned methods
3563 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3565 QObject *object = component.create();
3566 QVERIFY(object != 0);
3567 QCOMPARE(object->property("test").toReal(), 11.);
3572 void tst_qdeclarativeecmascript::realToInt()
3574 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3575 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3576 QVERIFY(object != 0);
3578 QMetaObject::invokeMethod(object, "test1");
3579 QCOMPARE(object->value(), int(4));
3580 QMetaObject::invokeMethod(object, "test2");
3581 QCOMPARE(object->value(), int(8));
3584 QTEST_MAIN(tst_qdeclarativeecmascript)
3586 #include "tst_qdeclarativeecmascript.moc"