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