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