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 QSKIP("Module API not supported with V8", SkipAll);
2590 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2591 QObject *object = component.create();
2592 QVERIFY(object != 0);
2593 QCOMPARE(object->property("existingUriTest").toInt(), 20);
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 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2608 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2611 // test that writing to a property of module apis works correctly.
2612 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2613 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2614 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2615 object = componentThree.create();
2616 QVERIFY(object != 0);
2617 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2618 QCOMPARE(object->property("writableProperty").toInt(), 50);
2619 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2620 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2621 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2622 QCOMPARE(object->property("writableProperty").toInt(), 30);
2625 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2626 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2627 object = failOne.create();
2628 QVERIFY(object == 0); // should have failed: invalid major version
2630 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2631 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2632 object = failTwo.create();
2633 QVERIFY(object == 0); // should have failed: invalid minor version
2636 void tst_qdeclarativeecmascript::importScripts()
2638 QObject *object = 0;
2640 // first, ensure that the required behaviour works.
2641 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2642 object = component.create();
2643 QVERIFY(object != 0);
2644 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2645 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2646 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2647 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2650 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2651 object = componentTwo.create();
2652 QVERIFY(object != 0);
2653 QCOMPARE(object->property("componentError"), QVariant(5));
2656 // then, ensure that unintended behaviour does not work.
2657 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2658 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2659 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2660 object = failOneComponent.create();
2661 QVERIFY(object != 0);
2662 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2664 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2665 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2666 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2667 object = failTwoComponent.create();
2668 QVERIFY(object != 0);
2669 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2671 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2672 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2673 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2674 object = failThreeComponent.create();
2675 QVERIFY(object != 0);
2676 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2678 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2679 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2680 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2681 object = failFourComponent.create();
2682 QVERIFY(object != 0);
2683 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2685 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2686 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2687 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2688 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2689 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2690 object = failFiveComponent.create();
2691 QVERIFY(object != 0);
2692 QCOMPARE(object->property("componentError"), QVariant(0));
2695 // also, test that importing scripts with .pragma library works as required
2696 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2697 object = pragmaLibraryComponent.create();
2698 QVERIFY(object != 0);
2699 QCOMPARE(object->property("testValue"), QVariant(31));
2702 // and that .pragma library scripts don't inherit imports from any .qml file
2703 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2704 object = pragmaLibraryComponentTwo.create();
2705 QVERIFY(object != 0);
2706 QCOMPARE(object->property("testValue"), QVariant(0));
2710 void tst_qdeclarativeecmascript::scarceResources()
2712 QPixmap origPixmap(100, 100);
2713 origPixmap.fill(Qt::blue);
2715 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2716 ScarceResourceObject *eo = 0;
2717 QObject *object = 0;
2719 // in the following three cases, the instance created from the component
2720 // has a property which is a copy of the scarce resource; hence, the
2721 // resource should NOT be detached prior to deletion of the object instance,
2722 // unless the resource is destroyed explicitly.
2723 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2724 object = component.create();
2725 QVERIFY(object != 0);
2726 QVERIFY(object->property("scarceResourceCopy").isValid());
2727 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2728 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2729 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2730 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2733 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2734 object = componentTwo.create();
2735 QVERIFY(object != 0);
2736 QVERIFY(object->property("scarceResourceCopy").isValid());
2737 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2738 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2739 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2740 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2743 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2744 object = componentThree.create();
2745 QVERIFY(object != 0);
2746 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2747 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2748 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2749 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2752 // in the following three cases, no other copy should exist in memory,
2753 // and so it should be detached (unless explicitly preserved).
2754 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2755 object = componentFour.create();
2756 QVERIFY(object != 0);
2757 QVERIFY(object->property("scarceResourceTest").isValid());
2758 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2759 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2760 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2761 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2764 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2765 object = componentFive.create();
2766 QVERIFY(object != 0);
2767 QVERIFY(object->property("scarceResourceTest").isValid());
2768 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2769 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2770 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2771 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2774 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2775 object = componentSix.create();
2776 QVERIFY(object != 0);
2777 QVERIFY(object->property("scarceResourceTest").isValid());
2778 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2779 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2780 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2781 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2784 // test that scarce resources are handled correctly for imports
2785 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2786 object = componentSeven.create();
2787 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2788 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
2791 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2792 object = componentEight.create();
2793 QVERIFY(object != 0);
2794 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2795 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2798 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2799 object = componentNine.create();
2800 QVERIFY(object != 0);
2801 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2802 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2803 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2804 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2805 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2806 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
2809 // test that scarce resources are handled properly in signal invocation
2810 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2811 object = componentTen.create();
2812 QVERIFY(object != 0);
2813 QObject *srsc = object->findChild<QObject*>("srsc");
2815 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2816 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2817 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2818 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2819 QMetaObject::invokeMethod(srsc, "testSignal");
2820 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2821 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2822 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2823 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2824 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2825 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2826 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2827 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2828 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2829 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2832 // test that scarce resources are handled properly from js functions in qml files
2833 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2834 object = componentEleven.create();
2835 QVERIFY(object != 0);
2836 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2837 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2838 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2839 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2840 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2841 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2842 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2843 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2844 QMetaObject::invokeMethod(object, "releaseScarceResource");
2845 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2846 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2847 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2848 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2851 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2852 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2853 object = componentTwelve.create();
2854 QVERIFY(object != 0);
2855 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2856 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2857 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2858 QString srp_name = object->property("srp_name").toString();
2859 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
2860 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
2861 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2862 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2863 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2864 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2865 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2869 void tst_qdeclarativeecmascript::propertyChangeSlots()
2871 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2872 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2873 QObject *object = component.create();
2874 QVERIFY(object != 0);
2877 // ensure that invalid property names fail properly.
2878 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2879 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2880 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2881 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2882 object = e1.create();
2883 QVERIFY(object == 0);
2886 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2887 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2888 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2889 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2890 object = e2.create();
2891 QVERIFY(object == 0);
2894 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2895 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2896 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2897 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2898 object = e3.create();
2899 QVERIFY(object == 0);
2902 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2903 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2904 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2905 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2906 object = e4.create();
2907 QVERIFY(object == 0);
2911 // Test that assigning a null object works
2912 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2913 void tst_qdeclarativeecmascript::nullObjectBinding()
2915 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2917 QObject *object = component.create();
2918 QVERIFY(object != 0);
2920 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2925 // Test that bindings don't evaluate once the engine has been destroyed
2926 void tst_qdeclarativeecmascript::deletedEngine()
2928 QDeclarativeEngine *engine = new QDeclarativeEngine;
2929 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2931 QObject *object = component.create();
2932 QVERIFY(object != 0);
2934 QCOMPARE(object->property("a").toInt(), 39);
2935 object->setProperty("b", QVariant(9));
2936 QCOMPARE(object->property("a").toInt(), 117);
2940 QCOMPARE(object->property("a").toInt(), 117);
2941 object->setProperty("b", QVariant(10));
2942 QCOMPARE(object->property("a").toInt(), 117);
2947 // Test the crashing part of QTBUG-9705
2948 void tst_qdeclarativeecmascript::libraryScriptAssert()
2950 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2952 QObject *object = component.create();
2953 QVERIFY(object != 0);
2958 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2960 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2962 QObject *object = component.create();
2963 QVERIFY(object != 0);
2965 QCOMPARE(object->property("test1").toInt(), 10);
2966 QCOMPARE(object->property("test2").toInt(), 11);
2968 object->setProperty("runTest", true);
2970 QCOMPARE(object->property("test1"), QVariant());
2971 QCOMPARE(object->property("test2"), QVariant());
2977 void tst_qdeclarativeecmascript::qtbug_9792()
2979 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
2981 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2983 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
2984 QVERIFY(object != 0);
2986 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
2987 object->basicSignal();
2991 transientErrorsMsgCount = 0;
2992 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2994 object->basicSignal();
2996 qInstallMsgHandler(old);
2998 QCOMPARE(transientErrorsMsgCount, 0);
3003 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3004 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3006 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3008 QObject *o = component.create();
3011 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3012 QVERIFY(nested != 0);
3014 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3017 nested = qvariant_cast<QObject *>(o->property("object"));
3018 QVERIFY(nested == 0);
3020 // If the bug is present, the next line will crash
3024 // Test that we shut down without stupid warnings
3025 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3028 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3030 QObject *o = component.create();
3032 transientErrorsMsgCount = 0;
3033 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3037 qInstallMsgHandler(old);
3039 QCOMPARE(transientErrorsMsgCount, 0);
3044 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3046 QObject *o = component.create();
3048 transientErrorsMsgCount = 0;
3049 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3053 qInstallMsgHandler(old);
3055 QCOMPARE(transientErrorsMsgCount, 0);
3059 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3062 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3064 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3067 QVERIFY(o->objectProperty() != 0);
3069 o->setProperty("runTest", true);
3071 QVERIFY(o->objectProperty() == 0);
3077 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3079 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3082 QVERIFY(o->objectProperty() == 0);
3088 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3090 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3092 QString url = component.url().toString();
3093 QString warning = url + ":4: Unable to assign a function to a property.";
3094 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3096 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3099 QVERIFY(!o->property("a").isValid());
3104 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3106 QFETCH(QString, triggerProperty);
3108 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3109 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3111 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3113 QVERIFY(!o->property("a").isValid());
3115 o->setProperty("aNumber", QVariant(5));
3116 o->setProperty(triggerProperty.toUtf8().constData(), true);
3117 QCOMPARE(o->property("a"), QVariant(50));
3119 o->setProperty("aNumber", QVariant(10));
3120 QCOMPARE(o->property("a"), QVariant(100));
3125 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3127 QTest::addColumn<QString>("triggerProperty");
3129 QTest::newRow("assign to property") << "assignToProperty";
3130 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3132 QTest::newRow("assign to value type") << "assignToValueType";
3134 QTest::newRow("use 'this'") << "assignWithThis";
3135 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3138 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3140 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3141 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3143 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3145 QVERIFY(!o->property("a").isValid());
3147 o->setProperty("assignFuncWithoutReturn", true);
3148 QVERIFY(!o->property("a").isValid());
3150 QString url = component.url().toString();
3151 QString warning = url + ":67: Unable to assign QString to int";
3152 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3153 o->setProperty("assignWrongType", true);
3155 warning = url + ":71: Unable to assign QString to int";
3156 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3157 o->setProperty("assignWrongTypeToValueType", true);
3162 void tst_qdeclarativeecmascript::eval()
3164 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3166 QObject *o = component.create();
3169 QCOMPARE(o->property("test1").toBool(), true);
3170 QCOMPARE(o->property("test2").toBool(), true);
3171 QCOMPARE(o->property("test3").toBool(), true);
3172 QCOMPARE(o->property("test4").toBool(), true);
3173 QCOMPARE(o->property("test5").toBool(), true);
3178 void tst_qdeclarativeecmascript::function()
3180 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3182 QObject *o = component.create();
3185 QCOMPARE(o->property("test1").toBool(), true);
3186 QCOMPARE(o->property("test2").toBool(), true);
3187 QCOMPARE(o->property("test3").toBool(), true);
3192 // Test the "Qt.include" method
3193 void tst_qdeclarativeecmascript::include()
3195 // Non-library relative include
3197 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3198 QObject *o = component.create();
3201 QCOMPARE(o->property("test0").toInt(), 99);
3202 QCOMPARE(o->property("test1").toBool(), true);
3203 QCOMPARE(o->property("test2").toBool(), true);
3204 QCOMPARE(o->property("test2_1").toBool(), true);
3205 QCOMPARE(o->property("test3").toBool(), true);
3206 QCOMPARE(o->property("test3_1").toBool(), true);
3211 // Library relative include
3213 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3214 QObject *o = component.create();
3217 QCOMPARE(o->property("test0").toInt(), 99);
3218 QCOMPARE(o->property("test1").toBool(), true);
3219 QCOMPARE(o->property("test2").toBool(), true);
3220 QCOMPARE(o->property("test2_1").toBool(), true);
3221 QCOMPARE(o->property("test3").toBool(), true);
3222 QCOMPARE(o->property("test3_1").toBool(), true);
3229 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3230 QObject *o = component.create();
3233 QCOMPARE(o->property("test1").toBool(), true);
3234 QCOMPARE(o->property("test2").toBool(), true);
3235 QCOMPARE(o->property("test3").toBool(), true);
3236 QCOMPARE(o->property("test4").toBool(), true);
3237 QCOMPARE(o->property("test5").toBool(), true);
3238 QCOMPARE(o->property("test6").toBool(), true);
3243 // Including file with ".pragma library"
3245 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3246 QObject *o = component.create();
3248 QCOMPARE(o->property("test1").toInt(), 100);
3255 TestHTTPServer server(8111);
3256 QVERIFY(server.isValid());
3257 server.serveDirectory(SRCDIR "/data");
3259 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3260 QObject *o = component.create();
3263 QTRY_VERIFY(o->property("done").toBool() == true);
3264 QTRY_VERIFY(o->property("done2").toBool() == true);
3266 QCOMPARE(o->property("test1").toBool(), true);
3267 QCOMPARE(o->property("test2").toBool(), true);
3268 QCOMPARE(o->property("test3").toBool(), true);
3269 QCOMPARE(o->property("test4").toBool(), true);
3270 QCOMPARE(o->property("test5").toBool(), true);
3272 QCOMPARE(o->property("test6").toBool(), true);
3273 QCOMPARE(o->property("test7").toBool(), true);
3274 QCOMPARE(o->property("test8").toBool(), true);
3275 QCOMPARE(o->property("test9").toBool(), true);
3276 QCOMPARE(o->property("test10").toBool(), true);
3283 TestHTTPServer server(8111);
3284 QVERIFY(server.isValid());
3285 server.serveDirectory(SRCDIR "/data");
3287 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3288 QObject *o = component.create();
3291 QTRY_VERIFY(o->property("done").toBool() == true);
3293 QCOMPARE(o->property("test1").toBool(), true);
3294 QCOMPARE(o->property("test2").toBool(), true);
3295 QCOMPARE(o->property("test3").toBool(), true);
3301 void tst_qdeclarativeecmascript::qtbug_10696()
3303 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3304 QObject *o = component.create();
3309 void tst_qdeclarativeecmascript::qtbug_11606()
3311 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3312 QObject *o = component.create();
3314 QCOMPARE(o->property("test").toBool(), true);
3318 void tst_qdeclarativeecmascript::qtbug_11600()
3320 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3321 QObject *o = component.create();
3323 QCOMPARE(o->property("test").toBool(), true);
3327 // Reading and writing non-scriptable properties should fail
3328 void tst_qdeclarativeecmascript::nonscriptable()
3330 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3331 QObject *o = component.create();
3333 QCOMPARE(o->property("readOk").toBool(), true);
3334 QCOMPARE(o->property("writeOk").toBool(), true);
3338 // deleteLater() should not be callable from QML
3339 void tst_qdeclarativeecmascript::deleteLater()
3341 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3342 QObject *o = component.create();
3344 QCOMPARE(o->property("test").toBool(), true);
3348 void tst_qdeclarativeecmascript::in()
3350 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3351 QObject *o = component.create();
3353 QCOMPARE(o->property("test1").toBool(), true);
3354 QCOMPARE(o->property("test2").toBool(), true);
3358 void tst_qdeclarativeecmascript::sharedAttachedObject()
3360 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3361 QObject *o = component.create();
3363 QCOMPARE(o->property("test1").toBool(), true);
3364 QCOMPARE(o->property("test2").toBool(), true);
3369 void tst_qdeclarativeecmascript::objectName()
3371 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3372 QObject *o = component.create();
3375 QCOMPARE(o->property("test1").toString(), QString("hello"));
3376 QCOMPARE(o->property("test2").toString(), QString("ell"));
3378 o->setObjectName("world");
3380 QCOMPARE(o->property("test1").toString(), QString("world"));
3381 QCOMPARE(o->property("test2").toString(), QString("orl"));
3386 void tst_qdeclarativeecmascript::writeRemovesBinding()
3388 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3389 QObject *o = component.create();
3392 QCOMPARE(o->property("test").toBool(), true);
3397 // Test bindings assigned to alias properties actually assign to the alias' target
3398 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3400 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3401 QObject *o = component.create();
3404 QCOMPARE(o->property("test").toBool(), true);
3409 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3410 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3413 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3414 QObject *o = component.create();
3417 QCOMPARE(o->property("test").toBool(), true);
3423 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3424 QObject *o = component.create();
3427 QCOMPARE(o->property("test").toBool(), true);
3433 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3434 QObject *o = component.create();
3437 QCOMPARE(o->property("test").toBool(), true);
3443 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3444 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3447 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3448 QObject *o = component.create();
3451 QCOMPARE(o->property("test").toBool(), true);
3457 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3458 QObject *o = component.create();
3461 QCOMPARE(o->property("test").toBool(), true);
3467 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3468 QObject *o = component.create();
3471 QCOMPARE(o->property("test").toBool(), true);
3477 void tst_qdeclarativeecmascript::revisionErrors()
3480 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3481 QString url = component.url().toString();
3483 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3484 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3485 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3487 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3488 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3489 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3490 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3491 QVERIFY(object != 0);
3495 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3496 QString url = component.url().toString();
3498 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3499 // method2, prop2 from MyRevisionedClass not available
3500 // method4, prop4 from MyRevisionedSubclass not available
3501 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3502 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3503 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3504 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3505 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3507 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3508 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3509 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3510 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3511 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3512 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3513 QVERIFY(object != 0);
3517 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3518 QString url = component.url().toString();
3520 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3521 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3522 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3523 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3524 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3525 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3526 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3527 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3528 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3529 QVERIFY(object != 0);
3534 void tst_qdeclarativeecmascript::revision()
3537 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3538 QString url = component.url().toString();
3540 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3541 QVERIFY(object != 0);
3545 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3546 QString url = component.url().toString();
3548 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3549 QVERIFY(object != 0);
3553 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3554 QString url = component.url().toString();
3556 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3557 QVERIFY(object != 0);
3560 // Test that non-root classes can resolve revisioned methods
3562 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3564 QObject *object = component.create();
3565 QVERIFY(object != 0);
3566 QCOMPARE(object->property("test").toReal(), 11.);
3571 void tst_qdeclarativeecmascript::realToInt()
3573 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3574 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3575 QVERIFY(object != 0);
3577 QMetaObject::invokeMethod(object, "test1");
3578 QCOMPARE(object->value(), int(4));
3579 QMetaObject::invokeMethod(object, "test2");
3580 QCOMPARE(object->value(), int(8));
3583 QTEST_MAIN(tst_qdeclarativeecmascript)
3585 #include "tst_qdeclarativeecmascript.moc"