Implement script module api property get and set
[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 "testtypes.h"
53 #include "testhttpserver.h"
54 #include "../../../shared/util.h"
55
56 #ifdef Q_OS_SYMBIAN
57 // In Symbian OS test data is located in applications private dir
58 #define SRCDIR "."
59 #endif
60
61 /*
62 This test covers evaluation of ECMAScript expressions and bindings from within
63 QML.  This does not include static QML language issues.
64
65 Static QML language issues are covered in qmllanguage
66 */
67 inline QUrl TEST_FILE(const QString &filename)
68 {
69     QFileInfo fileInfo(__FILE__);
70     return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
71 }
72
73 inline QUrl TEST_FILE(const char *filename)
74 {
75     return TEST_FILE(QLatin1String(filename));
76 }
77
78 class tst_qdeclarativeecmascript : public QObject
79 {
80     Q_OBJECT
81 public:
82     tst_qdeclarativeecmascript() {}
83
84 private slots:
85     void initTestCase();
86     void assignBasicTypes();
87     void idShortcutInvalidates();
88     void boolPropertiesEvaluateAsBool();
89     void methods();
90     void signalAssignment();
91     void bindingLoop();
92     void basicExpressions();
93     void basicExpressions_data();
94     void arrayExpressions();
95     void contextPropertiesTriggerReeval();
96     void objectPropertiesTriggerReeval();
97     void deferredProperties();
98     void deferredPropertiesErrors();
99     void extensionObjects();
100     void overrideExtensionProperties();
101     void attachedProperties();
102     void enums();
103     void valueTypeFunctions();
104     void constantsOverrideBindings();
105     void outerBindingOverridesInnerBinding();
106     void aliasPropertyAndBinding();
107     void aliasPropertyReset();
108     void nonExistentAttachedObject();
109     void scope();
110     void importScope();
111     void signalParameterTypes();
112     void objectsCompareAsEqual();
113     void dynamicCreation_data();
114     void dynamicCreation();
115     void dynamicDestruction();
116     void objectToString();
117     void objectHasOwnProperty();
118     void selfDeletingBinding();
119     void extendedObjectPropertyLookup();
120     void scriptErrors();
121     void functionErrors();
122     void propertyAssignmentErrors();
123     void signalTriggeredBindings();
124     void listProperties();
125     void exceptionClearsOnReeval();
126     void exceptionSlotProducesWarning();
127     void exceptionBindingProducesWarning();
128     void transientErrors();
129     void shutdownErrors();
130     void compositePropertyType();
131     void jsObject();
132     void undefinedResetsProperty();
133     void listToVariant();
134     void multiEngineObject();
135     void deletedObject();
136     void attachedPropertyScope();
137     void scriptConnect();
138     void scriptDisconnect();
139     void ownership();
140     void cppOwnershipReturnValue();
141     void ownershipCustomReturnValue();
142     void qlistqobjectMethods();
143     void strictlyEquals();
144     void compiled();
145     void numberAssignment();
146     void propertySplicing();
147     void signalWithUnknownTypes();
148     void moduleApi_data();
149     void moduleApi();
150     void importScripts();
151     void scarceResources();
152     void propertyChangeSlots();
153     void elementAssign();
154     void objectPassThroughSignals();
155     void booleanConversion();
156
157     void bug1();
158     void bug2();
159     void dynamicCreationCrash();
160     void regExpBug();
161     void nullObjectBinding();
162     void deletedEngine();
163     void libraryScriptAssert();
164     void variantsAssignedUndefined();
165     void qtbug_9792();
166     void qtcreatorbug_1289();
167     void noSpuriousWarningsAtShutdown();
168     void canAssignNullToQObject();
169     void functionAssignment_fromBinding();
170     void functionAssignment_fromJS();
171     void functionAssignment_fromJS_data();
172     void functionAssignmentfromJS_invalid();
173     void eval();
174     void function();
175     void qtbug_10696();
176     void qtbug_11606();
177     void qtbug_11600();
178     void nonscriptable();
179     void deleteLater();
180     void in();
181     void sharedAttachedObject();
182     void objectName();
183     void writeRemovesBinding();
184     void aliasBindingsAssignCorrectly();
185     void aliasBindingsOverrideTarget();
186     void aliasWritesOverrideBindings();
187     void aliasToCompositeElement();
188     void realToInt();
189     void dynamicString();
190     void include();
191
192     void callQtInvokables();
193     void invokableObjectArg();
194     void invokableObjectRet();
195
196     void revisionErrors();
197     void revision();
198
199 private:
200     QDeclarativeEngine engine;
201 };
202
203 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
204
205 void tst_qdeclarativeecmascript::assignBasicTypes()
206 {
207     {
208     QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
209     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
210     QVERIFY(object != 0);
211     QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
212     QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
213     QCOMPARE(object->stringProperty(), QString("Hello World!"));
214     QCOMPARE(object->uintProperty(), uint(10));
215     QCOMPARE(object->intProperty(), -19);
216     QCOMPARE((float)object->realProperty(), float(23.2));
217     QCOMPARE((float)object->doubleProperty(), float(-19.75));
218     QCOMPARE((float)object->floatProperty(), float(8.5));
219     QCOMPARE(object->colorProperty(), QColor("red"));
220     QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
221     QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
222     QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
223     QCOMPARE(object->pointProperty(), QPoint(99,13));
224     QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
225     QCOMPARE(object->sizeProperty(), QSize(99, 13));
226     QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
227     QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
228     QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
229     QCOMPARE(object->boolProperty(), true);
230     QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
231     QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
232     QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
233     delete object;
234     }
235     {
236     QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
237     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
238     QVERIFY(object != 0);
239     QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
240     QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
241     QCOMPARE(object->stringProperty(), QString("Hello World!"));
242     QCOMPARE(object->uintProperty(), uint(10));
243     QCOMPARE(object->intProperty(), -19);
244     QCOMPARE((float)object->realProperty(), float(23.2));
245     QCOMPARE((float)object->doubleProperty(), float(-19.75));
246     QCOMPARE((float)object->floatProperty(), float(8.5));
247     QCOMPARE(object->colorProperty(), QColor("red"));
248     QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
249     QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
250     QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
251     QCOMPARE(object->pointProperty(), QPoint(99,13));
252     QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
253     QCOMPARE(object->sizeProperty(), QSize(99, 13));
254     QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
255     QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
256     QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
257     QCOMPARE(object->boolProperty(), true);
258     QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
259     QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
260     QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
261     delete object;
262     }
263 }
264
265 void tst_qdeclarativeecmascript::idShortcutInvalidates()
266 {
267     {
268         QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
269         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
270         QVERIFY(object != 0);
271         QVERIFY(object->objectProperty() != 0);
272         delete object->objectProperty();
273         QVERIFY(object->objectProperty() == 0);
274         delete object;
275     }
276
277     {
278         QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
279         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
280         QVERIFY(object != 0);
281         QVERIFY(object->objectProperty() != 0);
282         delete object->objectProperty();
283         QVERIFY(object->objectProperty() == 0);
284         delete object;
285     }
286 }
287
288 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
289 {
290     {
291         QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
292         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
293         QVERIFY(object != 0);
294         QCOMPARE(object->stringProperty(), QLatin1String("pass"));
295         delete object;
296     }
297     {
298         QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
299         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
300         QVERIFY(object != 0);
301         QCOMPARE(object->stringProperty(), QLatin1String("pass"));
302         delete object;
303     }
304 }
305
306 void tst_qdeclarativeecmascript::signalAssignment()
307 {
308     {
309         QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
310         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
311         QVERIFY(object != 0);
312         QCOMPARE(object->string(), QString());
313         emit object->basicSignal();
314         QCOMPARE(object->string(), QString("pass"));
315         delete object;
316     }
317
318     {
319         QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
320         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
321         QVERIFY(object != 0);
322         QCOMPARE(object->string(), QString());
323         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
324         QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
325         delete object;
326     }
327 }
328
329 void tst_qdeclarativeecmascript::methods()
330 {
331     {
332         QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
333         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
334         QVERIFY(object != 0);
335         QCOMPARE(object->methodCalled(), false);
336         QCOMPARE(object->methodIntCalled(), false);
337         emit object->basicSignal();
338         QCOMPARE(object->methodCalled(), true);
339         QCOMPARE(object->methodIntCalled(), false);
340         delete object;
341     }
342
343     {
344         QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
345         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
346         QVERIFY(object != 0);
347         QCOMPARE(object->methodCalled(), false);
348         QCOMPARE(object->methodIntCalled(), false);
349         emit object->basicSignal();
350         QCOMPARE(object->methodCalled(), false);
351         QCOMPARE(object->methodIntCalled(), true);
352         delete object;
353     }
354
355     {
356         QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
357         QObject *object = component.create();
358         QVERIFY(object != 0);
359         QCOMPARE(object->property("test").toInt(), 19);
360         delete object;
361     }
362
363     {
364         QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
365         QObject *object = component.create();
366         QVERIFY(object != 0);
367         QCOMPARE(object->property("test").toInt(), 19);
368         QCOMPARE(object->property("test2").toInt(), 17);
369         QCOMPARE(object->property("test3").toInt(), 16);
370         delete object;
371     }
372
373     {
374         QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
375         QObject *object = component.create();
376         QVERIFY(object != 0);
377         QCOMPARE(object->property("test").toInt(), 9);
378         delete object;
379     }
380 }
381
382 void tst_qdeclarativeecmascript::bindingLoop()
383 {
384     QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
385     QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
386     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
387     QObject *object = component.create();
388     QVERIFY(object != 0);
389     delete object;
390 }
391
392 void tst_qdeclarativeecmascript::basicExpressions_data()
393 {
394     QTest::addColumn<QString>("expression");
395     QTest::addColumn<QVariant>("result");
396     QTest::addColumn<bool>("nest");
397
398     QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
399     QTest::newRow("Context property") << "a" << QVariant(1944) << false;
400     QTest::newRow("Context property") << "a" << QVariant(1944) << true;
401     QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
402     QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
403     QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
404     QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
405     QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
406     QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
407     QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
408     QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
409     QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
410     QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
411     QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
412     QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
413     QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
414     QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
415     QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
416     QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
417 }
418
419 void tst_qdeclarativeecmascript::basicExpressions()
420 {
421     QFETCH(QString, expression);
422     QFETCH(QVariant, result);
423     QFETCH(bool, nest);
424
425     MyQmlObject object1;
426     MyQmlObject object2;
427     MyQmlObject object3;
428     MyDefaultObject1 default1;
429     MyDefaultObject3 default3;
430     object1.setStringProperty("Object1");
431     object2.setStringProperty("Object2");
432     object3.setStringProperty("Object3");
433
434     QDeclarativeContext context(engine.rootContext());
435     QDeclarativeContext nestedContext(&context);
436
437     context.setContextObject(&default1);
438     context.setContextProperty("a", QVariant(1944));
439     context.setContextProperty("b", QVariant("Milk"));
440     context.setContextProperty("object", &object1);
441     context.setContextProperty("objectOverride", &object2);
442     nestedContext.setContextObject(&default3);
443     nestedContext.setContextProperty("b", QVariant("Cow"));
444     nestedContext.setContextProperty("objectOverride", &object3);
445     nestedContext.setContextProperty("millipedeLegs", QVariant(100));
446
447     MyExpression expr(nest?&nestedContext:&context, expression);
448     QCOMPARE(expr.evaluate(), result);
449 }
450
451 void tst_qdeclarativeecmascript::arrayExpressions()
452 {
453     QObject obj1;
454     QObject obj2;
455     QObject obj3;
456
457     QDeclarativeContext context(engine.rootContext());
458     context.setContextProperty("a", &obj1);
459     context.setContextProperty("b", &obj2);
460     context.setContextProperty("c", &obj3);
461
462     MyExpression expr(&context, "[a, b, c, 10]");
463     QVariant result = expr.evaluate();
464     QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
465     QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
466     QCOMPARE(list.count(), 4);
467     QCOMPARE(list.at(0), &obj1);
468     QCOMPARE(list.at(1), &obj2);
469     QCOMPARE(list.at(2), &obj3);
470     QCOMPARE(list.at(3), (QObject *)0);
471 }
472
473 // Tests that modifying a context property will reevaluate expressions
474 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
475 {
476     QDeclarativeContext context(engine.rootContext());
477     MyQmlObject object1;
478     MyQmlObject object2;
479     MyQmlObject *object3 = new MyQmlObject;
480
481     object1.setStringProperty("Hello");
482     object2.setStringProperty("World");
483
484     context.setContextProperty("testProp", QVariant(1));
485     context.setContextProperty("testObj", &object1);
486     context.setContextProperty("testObj2", object3);
487
488     { 
489         MyExpression expr(&context, "testProp + 1");
490         QCOMPARE(expr.changed, false);
491         QCOMPARE(expr.evaluate(), QVariant(2));
492
493         context.setContextProperty("testProp", QVariant(2));
494         QCOMPARE(expr.changed, true);
495         QCOMPARE(expr.evaluate(), QVariant(3));
496     }
497
498     { 
499         MyExpression expr(&context, "testProp + testProp + testProp");
500         QCOMPARE(expr.changed, false);
501         QCOMPARE(expr.evaluate(), QVariant(6));
502
503         context.setContextProperty("testProp", QVariant(4));
504         QCOMPARE(expr.changed, true);
505         QCOMPARE(expr.evaluate(), QVariant(12));
506     }
507
508     { 
509         MyExpression expr(&context, "testObj.stringProperty");
510         QCOMPARE(expr.changed, false);
511         QCOMPARE(expr.evaluate(), QVariant("Hello"));
512
513         context.setContextProperty("testObj", &object2);
514         QCOMPARE(expr.changed, true);
515         QCOMPARE(expr.evaluate(), QVariant("World"));
516     }
517
518     { 
519         MyExpression expr(&context, "testObj.stringProperty /**/");
520         QCOMPARE(expr.changed, false);
521         QCOMPARE(expr.evaluate(), QVariant("World"));
522
523         context.setContextProperty("testObj", &object1);
524         QCOMPARE(expr.changed, true);
525         QCOMPARE(expr.evaluate(), QVariant("Hello"));
526     }
527
528     { 
529         MyExpression expr(&context, "testObj2");
530         QCOMPARE(expr.changed, false);
531         QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
532     }
533
534     delete object3;
535 }
536
537 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
538 {
539     QDeclarativeContext context(engine.rootContext());
540     MyQmlObject object1;
541     MyQmlObject object2;
542     MyQmlObject object3;
543     context.setContextProperty("testObj", &object1);
544
545     object1.setStringProperty(QLatin1String("Hello"));
546     object2.setStringProperty(QLatin1String("Dog"));
547     object3.setStringProperty(QLatin1String("Cat"));
548
549     { 
550         MyExpression expr(&context, "testObj.stringProperty");
551         QCOMPARE(expr.changed, false);
552         QCOMPARE(expr.evaluate(), QVariant("Hello"));
553
554         object1.setStringProperty(QLatin1String("World"));
555         QCOMPARE(expr.changed, true);
556         QCOMPARE(expr.evaluate(), QVariant("World"));
557     }
558
559     { 
560         MyExpression expr(&context, "testObj.objectProperty.stringProperty");
561         QCOMPARE(expr.changed, false);
562         QCOMPARE(expr.evaluate(), QVariant());
563
564         object1.setObjectProperty(&object2);
565         QCOMPARE(expr.changed, true);
566         expr.changed = false;
567         QCOMPARE(expr.evaluate(), QVariant("Dog"));
568
569         object1.setObjectProperty(&object3);
570         QCOMPARE(expr.changed, true);
571         expr.changed = false;
572         QCOMPARE(expr.evaluate(), QVariant("Cat"));
573
574         object1.setObjectProperty(0);
575         QCOMPARE(expr.changed, true);
576         expr.changed = false;
577         QCOMPARE(expr.evaluate(), QVariant());
578
579         object1.setObjectProperty(&object3);
580         QCOMPARE(expr.changed, true);
581         expr.changed = false;
582         QCOMPARE(expr.evaluate(), QVariant("Cat"));
583
584         object3.setStringProperty("Donkey");
585         QCOMPARE(expr.changed, true);
586         expr.changed = false;
587         QCOMPARE(expr.evaluate(), QVariant("Donkey"));
588     }
589 }
590
591 void tst_qdeclarativeecmascript::deferredProperties()
592 {
593     QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
594     MyDeferredObject *object = 
595         qobject_cast<MyDeferredObject *>(component.create());
596     QVERIFY(object != 0);
597     QCOMPARE(object->value(), 0);
598     QVERIFY(object->objectProperty() == 0);
599     QVERIFY(object->objectProperty2() != 0);
600     qmlExecuteDeferred(object);
601     QCOMPARE(object->value(), 10);
602     QVERIFY(object->objectProperty() != 0);
603     MyQmlObject *qmlObject = 
604         qobject_cast<MyQmlObject *>(object->objectProperty());
605     QVERIFY(qmlObject != 0);
606     QCOMPARE(qmlObject->value(), 10);
607     object->setValue(19);
608     QCOMPARE(qmlObject->value(), 19);
609
610     delete object;
611 }
612
613 // Check errors on deferred properties are correctly emitted
614 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
615 {
616     QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
617     MyDeferredObject *object = 
618         qobject_cast<MyDeferredObject *>(component.create());
619     QVERIFY(object != 0);
620     QCOMPARE(object->value(), 0);
621     QVERIFY(object->objectProperty() == 0);
622     QVERIFY(object->objectProperty2() == 0);
623
624     QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
625     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
626
627     qmlExecuteDeferred(object);
628
629     delete object;
630 }
631
632 void tst_qdeclarativeecmascript::extensionObjects()
633 {
634     QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
635     MyExtendedObject *object = 
636         qobject_cast<MyExtendedObject *>(component.create());
637     QVERIFY(object != 0);
638     QCOMPARE(object->baseProperty(), 13);
639     QCOMPARE(object->coreProperty(), 9);
640     object->setProperty("extendedProperty", QVariant(11));
641     object->setProperty("baseExtendedProperty", QVariant(92));
642     QCOMPARE(object->coreProperty(), 11);
643     QCOMPARE(object->baseProperty(), 92);
644
645     MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
646     QVERIFY(nested);
647     QCOMPARE(nested->baseProperty(), 13);
648     QCOMPARE(nested->coreProperty(), 9);
649     nested->setProperty("extendedProperty", QVariant(11));
650     nested->setProperty("baseExtendedProperty", QVariant(92));
651     QCOMPARE(nested->coreProperty(), 11);
652     QCOMPARE(nested->baseProperty(), 92);
653
654     delete object;
655 }
656
657 void tst_qdeclarativeecmascript::overrideExtensionProperties()
658 {
659     QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
660     OverrideDefaultPropertyObject *object =
661         qobject_cast<OverrideDefaultPropertyObject *>(component.create());
662     QVERIFY(object != 0);
663     QVERIFY(object->secondProperty() != 0);
664     QVERIFY(object->firstProperty() == 0);
665
666     delete object;
667 }
668
669 void tst_qdeclarativeecmascript::attachedProperties()
670 {
671     {
672         QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
673         QObject *object = component.create();
674         QVERIFY(object != 0);
675         QCOMPARE(object->property("a").toInt(), 19);
676         QCOMPARE(object->property("b").toInt(), 19);
677         QCOMPARE(object->property("c").toInt(), 19);
678         QCOMPARE(object->property("d").toInt(), 19);
679         delete object;
680     }
681
682     {
683         QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
684         QObject *object = component.create();
685         QVERIFY(object != 0);
686         QCOMPARE(object->property("a").toInt(), 26);
687         QCOMPARE(object->property("b").toInt(), 26);
688         QCOMPARE(object->property("c").toInt(), 26);
689         QCOMPARE(object->property("d").toInt(), 26);
690     }
691
692     {
693         QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
694         QObject *object = component.create();
695         QVERIFY(object != 0);
696
697         QMetaObject::invokeMethod(object, "writeValue2");
698
699         MyQmlAttachedObject *attached =
700             qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
701         QVERIFY(attached != 0);
702
703         QCOMPARE(attached->value2(), 9);
704         delete object;
705     }
706 }
707
708 void tst_qdeclarativeecmascript::enums()
709 {
710     // Existent enums
711     {
712     QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
713     QObject *object = component.create();
714     QVERIFY(object != 0);
715
716     QCOMPARE(object->property("a").toInt(), 0);
717     QCOMPARE(object->property("b").toInt(), 1);
718     QCOMPARE(object->property("c").toInt(), 2);
719     QCOMPARE(object->property("d").toInt(), 3);
720     QCOMPARE(object->property("e").toInt(), 0);
721     QCOMPARE(object->property("f").toInt(), 1);
722     QCOMPARE(object->property("g").toInt(), 2);
723     QCOMPARE(object->property("h").toInt(), 3);
724     QCOMPARE(object->property("i").toInt(), 19);
725     QCOMPARE(object->property("j").toInt(), 19);
726
727     delete object;
728     }
729     // Non-existent enums
730     {
731     QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
732
733     QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
734     QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
735     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
736     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
737
738     QObject *object = component.create();
739     QVERIFY(object != 0);
740     QCOMPARE(object->property("a").toInt(), 0);
741     QCOMPARE(object->property("b").toInt(), 0);
742
743     delete object;
744     }
745 }
746
747 void tst_qdeclarativeecmascript::valueTypeFunctions()
748 {
749     QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
750     MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
751     QVERIFY(obj != 0);
752     QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
753     QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
754
755     delete obj;
756 }
757
758 /* 
759 Tests that writing a constant to a property with a binding on it disables the
760 binding.
761 */
762 void tst_qdeclarativeecmascript::constantsOverrideBindings()
763 {
764     // From ECMAScript
765     {
766         QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
767         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
768         QVERIFY(object != 0);
769
770         QCOMPARE(object->property("c2").toInt(), 0);
771         object->setProperty("c1", QVariant(9));
772         QCOMPARE(object->property("c2").toInt(), 9);
773
774         emit object->basicSignal();
775
776         QCOMPARE(object->property("c2").toInt(), 13);
777         object->setProperty("c1", QVariant(8));
778         QCOMPARE(object->property("c2").toInt(), 13);
779
780         delete object;
781     }
782
783     // During construction
784     {
785         QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
786         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
787         QVERIFY(object != 0);
788
789         QCOMPARE(object->property("c1").toInt(), 0);
790         QCOMPARE(object->property("c2").toInt(), 10);
791         object->setProperty("c1", QVariant(9));
792         QCOMPARE(object->property("c1").toInt(), 9);
793         QCOMPARE(object->property("c2").toInt(), 10);
794
795         delete object;
796     }
797
798 #if 0
799     // From C++
800     {
801         QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
802         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
803         QVERIFY(object != 0);
804
805         QCOMPARE(object->property("c2").toInt(), 0);
806         object->setProperty("c1", QVariant(9));
807         QCOMPARE(object->property("c2").toInt(), 9);
808
809         object->setProperty("c2", QVariant(13));
810         QCOMPARE(object->property("c2").toInt(), 13);
811         object->setProperty("c1", QVariant(7));
812         QCOMPARE(object->property("c1").toInt(), 7);
813         QCOMPARE(object->property("c2").toInt(), 13);
814
815         delete object;
816     }
817 #endif
818
819     // Using an alias
820     {
821         QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
822         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
823         QVERIFY(object != 0);
824
825         QCOMPARE(object->property("c1").toInt(), 0);
826         QCOMPARE(object->property("c3").toInt(), 10);
827         object->setProperty("c1", QVariant(9));
828         QCOMPARE(object->property("c1").toInt(), 9);
829         QCOMPARE(object->property("c3").toInt(), 10);
830
831         delete object;
832     }
833 }
834
835 /*
836 Tests that assigning a binding to a property that already has a binding causes
837 the original binding to be disabled.
838 */
839 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
840 {
841     QDeclarativeComponent component(&engine, 
842                            TEST_FILE("outerBindingOverridesInnerBinding.qml"));
843     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
844     QVERIFY(object != 0);
845
846     QCOMPARE(object->property("c1").toInt(), 0);
847     QCOMPARE(object->property("c2").toInt(), 0);
848     QCOMPARE(object->property("c3").toInt(), 0);
849
850     object->setProperty("c1", QVariant(9));
851     QCOMPARE(object->property("c1").toInt(), 9);
852     QCOMPARE(object->property("c2").toInt(), 0);
853     QCOMPARE(object->property("c3").toInt(), 0);
854
855     object->setProperty("c3", QVariant(8));
856     QCOMPARE(object->property("c1").toInt(), 9);
857     QCOMPARE(object->property("c2").toInt(), 8);
858     QCOMPARE(object->property("c3").toInt(), 8);
859
860     delete object;
861 }
862
863 /*
864 Access a non-existent attached object.  
865
866 Tests for a regression where this used to crash.
867 */
868 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
869 {
870     QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
871
872     QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
873     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
874
875     QObject *object = component.create();
876     QVERIFY(object != 0);
877
878     delete object;
879 }
880
881 void tst_qdeclarativeecmascript::scope()
882 {
883     {
884         QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
885         QObject *object = component.create();
886         QVERIFY(object != 0);
887
888         QCOMPARE(object->property("test1").toInt(), 1);
889         QCOMPARE(object->property("test2").toInt(), 2);
890         QCOMPARE(object->property("test3").toString(), QString("1Test"));
891         QCOMPARE(object->property("test4").toString(), QString("2Test"));
892         QCOMPARE(object->property("test5").toInt(), 1);
893         QCOMPARE(object->property("test6").toInt(), 1);
894         QCOMPARE(object->property("test7").toInt(), 2);
895         QCOMPARE(object->property("test8").toInt(), 2);
896         QCOMPARE(object->property("test9").toInt(), 1);
897         QCOMPARE(object->property("test10").toInt(), 3);
898
899         delete object;
900     }
901
902     {
903         QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
904         QObject *object = component.create();
905         QVERIFY(object != 0);
906
907         QCOMPARE(object->property("test1").toInt(), 19);
908         QCOMPARE(object->property("test2").toInt(), 19);
909         QCOMPARE(object->property("test3").toInt(), 14);
910         QCOMPARE(object->property("test4").toInt(), 14);
911         QCOMPARE(object->property("test5").toInt(), 24);
912         QCOMPARE(object->property("test6").toInt(), 24);
913
914         delete object;
915     }
916
917     {
918         QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
919         QObject *object = component.create();
920         QVERIFY(object != 0);
921
922         QCOMPARE(object->property("test1").toBool(), true);
923         QCOMPARE(object->property("test2").toBool(), true);
924         QCOMPARE(object->property("test3").toBool(), true);
925
926         delete object;
927     }
928
929     // Signal argument scope
930     {
931         QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
932         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
933         QVERIFY(object != 0);
934
935         QCOMPARE(object->property("test").toInt(), 0);
936         QCOMPARE(object->property("test2").toString(), QString());
937
938         emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
939
940         QCOMPARE(object->property("test").toInt(), 13);
941         QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
942
943         delete object;
944     }
945
946     {
947         QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
948         QObject *object = component.create();
949         QVERIFY(object != 0);
950
951         QCOMPARE(object->property("test1").toBool(), true);
952         QCOMPARE(object->property("test2").toBool(), true);
953
954         delete object;
955     }
956
957     {
958         QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
959         QObject *object = component.create();
960         QVERIFY(object != 0);
961
962         QCOMPARE(object->property("test").toBool(), true);
963
964         delete object;
965     }
966 }
967
968 // In 4.7, non-library javascript files that had no imports shared the imports of their
969 // importing context
970 void tst_qdeclarativeecmascript::importScope()
971 {
972     QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
973     QObject *o = component.create();
974     QVERIFY(o != 0);
975
976     QCOMPARE(o->property("test").toInt(), 240);
977
978     delete o;
979 }
980
981 /*
982 Tests that "any" type passes through a synthesized signal parameter.  This
983 is essentially a test of QDeclarativeMetaType::copy()
984 */
985 void tst_qdeclarativeecmascript::signalParameterTypes()
986 {
987     QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
988     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
989     QVERIFY(object != 0);
990
991     emit object->basicSignal();
992
993     QCOMPARE(object->property("intProperty").toInt(), 10);
994     QCOMPARE(object->property("realProperty").toReal(), 19.2);
995     QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
996     QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
997     QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
998     QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
999
1000     delete object;
1001 }
1002
1003 /*
1004 Test that two JS objects for the same QObject compare as equal.
1005 */
1006 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1007 {
1008     QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1009     QObject *object = component.create();
1010     QVERIFY(object != 0);
1011
1012     QCOMPARE(object->property("test1").toBool(), true);
1013     QCOMPARE(object->property("test2").toBool(), true);
1014     QCOMPARE(object->property("test3").toBool(), true);
1015     QCOMPARE(object->property("test4").toBool(), true);
1016     QCOMPARE(object->property("test5").toBool(), true);
1017
1018     delete object;
1019 }
1020
1021 /*
1022 Confirm bindings and alias properties can coexist.
1023
1024 Tests for a regression where the binding would not reevaluate.
1025 */
1026 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1027 {
1028     QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1029     QObject *object = component.create();
1030     QVERIFY(object != 0);
1031
1032     QCOMPARE(object->property("c2").toInt(), 3);
1033     QCOMPARE(object->property("c3").toInt(), 3);
1034
1035     object->setProperty("c2", QVariant(19));
1036
1037     QCOMPARE(object->property("c2").toInt(), 19);
1038     QCOMPARE(object->property("c3").toInt(), 19);
1039
1040     delete object;
1041 }
1042
1043 /*
1044 Ensure that we can write undefined value to an alias property,
1045 and that the aliased property is reset correctly if possible.
1046 */
1047 void tst_qdeclarativeecmascript::aliasPropertyReset()
1048 {
1049     QObject *object = 0;
1050
1051     // test that a manual write (of undefined) to a resettable aliased property succeeds
1052     QDeclarativeComponent c1(&engine, TEST_FILE("aliasreset/aliasPropertyReset.1.qml"));
1053     object = c1.create();
1054     QVERIFY(object != 0);
1055     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1056     QCOMPARE(object->property("aliasIsUndefined"), QVariant(false));
1057     QMetaObject::invokeMethod(object, "resetAliased");
1058     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1059     QCOMPARE(object->property("aliasIsUndefined"), QVariant(true));
1060     delete object;
1061
1062     // test that a manual write (of undefined) to a resettable alias property succeeds
1063     QDeclarativeComponent c2(&engine, TEST_FILE("aliasreset/aliasPropertyReset.2.qml"));
1064     object = c2.create();
1065     QVERIFY(object != 0);
1066     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1067     QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(false));
1068     QMetaObject::invokeMethod(object, "resetAlias");
1069     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1070     QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(true));
1071     delete object;
1072
1073     // test that an alias to a bound property works correctly
1074     QDeclarativeComponent c3(&engine, TEST_FILE("aliasreset/aliasPropertyReset.3.qml"));
1075     object = c3.create();
1076     QVERIFY(object != 0);
1077     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1078     QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(false));
1079     QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1080     QMetaObject::invokeMethod(object, "resetAlias");
1081     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1082     QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(true));
1083     QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1084     delete object;
1085
1086     // test that a manual write (of undefined) to a resettable alias property
1087     // whose aliased property's object has been deleted, does not crash.
1088     QDeclarativeComponent c4(&engine, TEST_FILE("aliasreset/aliasPropertyReset.4.qml"));
1089     object = c4.create();
1090     QVERIFY(object != 0);
1091     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1092     QObject *loader = object->findChild<QObject*>("loader");
1093     QVERIFY(loader != 0);
1094     delete loader;
1095     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // deletion should have caused value unset.
1096     QMetaObject::invokeMethod(object, "resetAlias"); // shouldn't crash.
1097     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1098     QMetaObject::invokeMethod(object, "setAlias");   // shouldn't crash, and shouldn't change value (since it's no longer referencing anything).
1099     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1100     delete object;
1101
1102     // test that binding an alias property to an undefined value works correctly
1103     QDeclarativeComponent c5(&engine, TEST_FILE("aliasreset/aliasPropertyReset.5.qml"));
1104     object = c5.create();
1105     QVERIFY(object != 0);
1106     QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // bound to undefined value.
1107     delete object;
1108
1109     // test that a manual write (of undefined) to a non-resettable property fails properly
1110     QUrl url = TEST_FILE("aliasreset/aliasPropertyReset.error.1.qml");
1111     QString warning1 = url.toString() + QLatin1String(":15: Error: Cannot assign [undefined] to int");
1112     QDeclarativeComponent e1(&engine, url);
1113     object = e1.create();
1114     QVERIFY(object != 0);
1115     QCOMPARE(object->property("intAlias").value<int>(), 12);
1116     QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1117     QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1118     QMetaObject::invokeMethod(object, "resetAlias");
1119     QCOMPARE(object->property("intAlias").value<int>(), 12);
1120     QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1121     delete object;
1122 }
1123
1124 void tst_qdeclarativeecmascript::dynamicCreation_data()
1125 {
1126     QTest::addColumn<QString>("method");
1127     QTest::addColumn<QString>("createdName");
1128
1129     QTest::newRow("One") << "createOne" << "objectOne";
1130     QTest::newRow("Two") << "createTwo" << "objectTwo";
1131     QTest::newRow("Three") << "createThree" << "objectThree";
1132 }
1133
1134 /*
1135 Test using createQmlObject to dynamically generate an item
1136 Also using createComponent is tested.
1137 */
1138 void tst_qdeclarativeecmascript::dynamicCreation()
1139 {
1140     QFETCH(QString, method);
1141     QFETCH(QString, createdName);
1142
1143     QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1144     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1145     QVERIFY(object != 0);
1146
1147     QMetaObject::invokeMethod(object, method.toUtf8());
1148     QObject *created = object->objectProperty();
1149     QVERIFY(created);
1150     QCOMPARE(created->objectName(), createdName);
1151
1152     delete object;
1153 }
1154
1155 /*
1156    Tests the destroy function
1157 */
1158 void tst_qdeclarativeecmascript::dynamicDestruction()
1159 {
1160     {
1161     QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1162     QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1163     QVERIFY(object != 0);
1164     QDeclarativeGuard<QObject> createdQmlObject = 0;
1165
1166     QMetaObject::invokeMethod(object, "create");
1167     createdQmlObject = object->objectProperty();
1168     QVERIFY(createdQmlObject);
1169     QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1170
1171     QMetaObject::invokeMethod(object, "killOther");
1172     QVERIFY(createdQmlObject);
1173     QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1174     QVERIFY(createdQmlObject);
1175     for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1176         if (createdQmlObject) {
1177             QTest::qWait(100);
1178             QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1179         }
1180     }
1181     QVERIFY(!createdQmlObject);
1182
1183     QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1184     QMetaObject::invokeMethod(object, "killMe");
1185     QVERIFY(object);
1186     QTest::qWait(0);
1187     QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1188     QVERIFY(!object);
1189     }
1190
1191     {
1192     QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.2.qml"));
1193     QObject *o = component.create();
1194     QVERIFY(o != 0);
1195
1196     QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1197
1198     QMetaObject::invokeMethod(o, "create");
1199
1200     QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
1201
1202     QMetaObject::invokeMethod(o, "destroy");
1203
1204     QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1205
1206     QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1207
1208     delete o;
1209     }
1210 }
1211
1212 /*
1213    tests that id.toString() works
1214 */
1215 void tst_qdeclarativeecmascript::objectToString()
1216 {
1217     QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1218     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1219     QVERIFY(object != 0);
1220     QMetaObject::invokeMethod(object, "testToString");
1221     QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1222     QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1223
1224     delete object;
1225 }
1226
1227 /*
1228   tests that id.hasOwnProperty() works
1229 */
1230 void tst_qdeclarativeecmascript::objectHasOwnProperty()
1231 {
1232     QUrl url = TEST_FILE("declarativeHasOwnProperty.qml");
1233     QString warning1 = url.toString() + ":59: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1234     QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1235     QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1236
1237     QDeclarativeComponent component(&engine, url);
1238     QObject *object = component.create();
1239     QVERIFY(object != 0);
1240
1241     // test QObjects in QML
1242     QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
1243     QVERIFY(object->property("result").value<bool>() == true);
1244     QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
1245     QVERIFY(object->property("result").value<bool>() == false);
1246
1247     // now test other types in QML
1248     QObject *child = object->findChild<QObject*>("typeObj");
1249     QVERIFY(child != 0);
1250     QMetaObject::invokeMethod(child, "testHasOwnPropertySuccess");
1251     QCOMPARE(child->property("valueTypeHasOwnProperty").toBool(), true);
1252     QCOMPARE(child->property("valueTypeHasOwnProperty2").toBool(), true);
1253     QCOMPARE(child->property("variantTypeHasOwnProperty").toBool(), true);
1254     QCOMPARE(child->property("stringTypeHasOwnProperty").toBool(), true);
1255     QCOMPARE(child->property("listTypeHasOwnProperty").toBool(), true);
1256     QCOMPARE(child->property("emptyListTypeHasOwnProperty").toBool(), true);
1257     QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
1258     QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
1259     QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
1260     QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
1261     QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
1262
1263     QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1264     QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
1265     QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
1266     QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1267     QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
1268     QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
1269     QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1270     QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
1271     QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
1272
1273     delete object;
1274 }
1275
1276 /*
1277 Tests bindings that indirectly cause their own deletion work.
1278
1279 This test is best run under valgrind to ensure no invalid memory access occur.
1280 */
1281 void tst_qdeclarativeecmascript::selfDeletingBinding()
1282 {
1283     {
1284         QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1285         QObject *object = component.create();
1286         QVERIFY(object != 0);
1287         object->setProperty("triggerDelete", true);
1288         delete object;
1289     }
1290
1291     {
1292         QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1293         QObject *object = component.create();
1294         QVERIFY(object != 0);
1295         object->setProperty("triggerDelete", true);
1296         delete object;
1297     }
1298 }
1299
1300 /*
1301 Test that extended object properties can be accessed.
1302
1303 This test a regression where this used to crash.  The issue was specificially
1304 for extended objects that did not include a synthesized meta object (so non-root
1305 and no synthesiszed properties).
1306 */
1307 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1308 {
1309     QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1310     QObject *object = component.create();
1311     QVERIFY(object != 0);
1312     delete object;
1313 }
1314
1315 /*
1316 Test file/lineNumbers for binding/Script errors.
1317 */
1318 void tst_qdeclarativeecmascript::scriptErrors()
1319 {
1320     QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1321     QString url = component.url().toString();
1322
1323     QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1324     QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1325     QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1326     QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1327     QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1328     QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1329     QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1330     QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1331
1332     QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1333     QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1334     QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1335     QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1336     QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1337     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1338     QVERIFY(object != 0);
1339
1340     QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1341     emit object->basicSignal();
1342
1343     QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1344     emit object->anotherBasicSignal();
1345
1346     QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1347     emit object->thirdBasicSignal();
1348
1349     delete object;
1350 }
1351
1352 /*
1353 Test file/lineNumbers for inline functions.
1354 */
1355 void tst_qdeclarativeecmascript::functionErrors()
1356 {
1357     QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1358     QString url = component.url().toString();
1359
1360     QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1361
1362     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1363
1364     QObject *object = component.create();
1365     QVERIFY(object != 0);
1366     delete object;
1367
1368     // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1369     QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1370     url = componentTwo.url().toString();
1371     object = componentTwo.create();
1372     QVERIFY(object != 0);
1373
1374     QString srpname = object->property("srp_name").toString();
1375     
1376     warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname + 
1377               QLatin1String(" is not a function");
1378     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1379     QMetaObject::invokeMethod(object, "retrieveScarceResource");
1380     delete object;
1381 }
1382
1383 /*
1384 Test various errors that can occur when assigning a property from script
1385 */
1386 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1387 {
1388     QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1389
1390     QString url = component.url().toString();
1391
1392     QObject *object = component.create();
1393     QVERIFY(object != 0);
1394
1395     QCOMPARE(object->property("test1").toBool(), true);
1396     QCOMPARE(object->property("test2").toBool(), true);
1397
1398     delete object;
1399 }
1400     
1401 /*
1402 Test bindings still work when the reeval is triggered from within
1403 a signal script.
1404 */
1405 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1406 {
1407     QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1408     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1409     QVERIFY(object != 0);
1410
1411     QCOMPARE(object->property("base").toReal(), 50.);
1412     QCOMPARE(object->property("test1").toReal(), 50.);
1413     QCOMPARE(object->property("test2").toReal(), 50.);
1414
1415     object->basicSignal();
1416
1417     QCOMPARE(object->property("base").toReal(), 200.);
1418     QCOMPARE(object->property("test1").toReal(), 200.);
1419     QCOMPARE(object->property("test2").toReal(), 200.);
1420
1421     object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1422
1423     QCOMPARE(object->property("base").toReal(), 400.);
1424     QCOMPARE(object->property("test1").toReal(), 400.);
1425     QCOMPARE(object->property("test2").toReal(), 400.);
1426
1427     delete object;
1428 }
1429
1430 /*
1431 Test that list properties can be iterated from ECMAScript
1432 */
1433 void tst_qdeclarativeecmascript::listProperties()
1434 {
1435     QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1436     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1437     QVERIFY(object != 0);
1438
1439     QCOMPARE(object->property("test1").toInt(), 21);
1440     QCOMPARE(object->property("test2").toInt(), 2);
1441     QCOMPARE(object->property("test3").toBool(), true);
1442     QCOMPARE(object->property("test4").toBool(), true);
1443
1444     delete object;
1445 }
1446
1447 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1448 {
1449     QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1450     QString url = component.url().toString();
1451
1452     QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1453
1454     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1455     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1456     QVERIFY(object != 0);
1457
1458     QCOMPARE(object->property("test").toBool(), false);
1459
1460     MyQmlObject object2;
1461     MyQmlObject object3;
1462     object2.setObjectProperty(&object3);
1463     object->setObjectProperty(&object2);
1464
1465     QCOMPARE(object->property("test").toBool(), true);
1466
1467     delete object;
1468 }
1469
1470 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1471 {
1472     QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1473     QString url = component.url().toString();
1474
1475     QString warning = component.url().toString() + ":6: Error: JS exception";
1476
1477     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1478     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1479     QVERIFY(object != 0);
1480     delete object;
1481 }
1482
1483 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1484 {
1485     QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1486     QString url = component.url().toString();
1487
1488     QString warning = component.url().toString() + ":5: Error: JS exception";
1489
1490     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1491     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1492     QVERIFY(object != 0);
1493     delete object;
1494 }
1495
1496 static int transientErrorsMsgCount = 0;
1497 static void transientErrorsMsgHandler(QtMsgType, const char *)
1498 {
1499     ++transientErrorsMsgCount;
1500 }
1501
1502 // Check that transient binding errors are not displayed
1503 void tst_qdeclarativeecmascript::transientErrors()
1504 {
1505     {
1506     QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1507
1508     transientErrorsMsgCount = 0;
1509     QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1510
1511     QObject *object = component.create();
1512     QVERIFY(object != 0);
1513
1514     qInstallMsgHandler(old);
1515
1516     QCOMPARE(transientErrorsMsgCount, 0);
1517
1518     delete object;
1519     }
1520
1521     // One binding erroring multiple times, but then resolving
1522     {
1523     QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1524
1525     transientErrorsMsgCount = 0;
1526     QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1527
1528     QObject *object = component.create();
1529     QVERIFY(object != 0);
1530
1531     qInstallMsgHandler(old);
1532
1533     QCOMPARE(transientErrorsMsgCount, 0);
1534
1535     delete object;
1536     }
1537 }
1538
1539 // Check that errors during shutdown are minimized
1540 void tst_qdeclarativeecmascript::shutdownErrors()
1541 {
1542     QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1543     QObject *object = component.create();
1544     QVERIFY(object != 0);
1545
1546     transientErrorsMsgCount = 0;
1547     QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1548
1549     delete object;
1550
1551     qInstallMsgHandler(old);
1552     QCOMPARE(transientErrorsMsgCount, 0);
1553 }
1554
1555 void tst_qdeclarativeecmascript::compositePropertyType()
1556 {
1557     QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1558     QTest::ignoreMessage(QtDebugMsg, "hello world");
1559     QObject *object = qobject_cast<QObject *>(component.create());
1560     delete object;
1561 }
1562
1563 // QTBUG-5759
1564 void tst_qdeclarativeecmascript::jsObject()
1565 {
1566     QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1567     QObject *object = component.create();
1568     QVERIFY(object != 0);
1569
1570     QCOMPARE(object->property("test").toInt(), 92);
1571
1572     delete object;
1573 }
1574
1575 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1576 {
1577     {
1578     QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1579     QObject *object = component.create();
1580     QVERIFY(object != 0);
1581
1582     QCOMPARE(object->property("resettableProperty").toInt(), 92);
1583
1584     object->setProperty("setUndefined", true);
1585
1586     QCOMPARE(object->property("resettableProperty").toInt(), 13);
1587
1588     object->setProperty("setUndefined", false);
1589
1590     QCOMPARE(object->property("resettableProperty").toInt(), 92);
1591
1592     delete object;
1593     }
1594     {
1595     QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1596     QObject *object = component.create();
1597     QVERIFY(object != 0);
1598
1599     QCOMPARE(object->property("resettableProperty").toInt(), 19);
1600
1601     QMetaObject::invokeMethod(object, "doReset");
1602
1603     QCOMPARE(object->property("resettableProperty").toInt(), 13);
1604
1605     delete object;
1606     }
1607 }
1608
1609 // QTBUG-6781
1610 void tst_qdeclarativeecmascript::bug1()
1611 {
1612     QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1613     QObject *object = component.create();
1614     QVERIFY(object != 0);
1615
1616     QCOMPARE(object->property("test").toInt(), 14);
1617
1618     object->setProperty("a", 11);
1619
1620     QCOMPARE(object->property("test").toInt(), 3);
1621
1622     object->setProperty("b", true);
1623
1624     QCOMPARE(object->property("test").toInt(), 9);
1625
1626     delete object;
1627 }
1628
1629 void tst_qdeclarativeecmascript::bug2()
1630 {
1631     QDeclarativeComponent component(&engine);
1632     component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1633
1634     QObject *object = component.create();
1635     QVERIFY(object != 0);
1636
1637     delete object;
1638 }
1639
1640 // Don't crash in createObject when the component has errors.
1641 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1642 {
1643     QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1644     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1645     QVERIFY(object != 0);
1646
1647     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1648     QMetaObject::invokeMethod(object, "dontCrash");
1649     QObject *created = object->objectProperty();
1650     QVERIFY(created == 0);
1651
1652     delete object;
1653 }
1654
1655 //QTBUG-9367
1656 void tst_qdeclarativeecmascript::regExpBug()
1657 {
1658     QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1659     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1660     QVERIFY(object != 0);
1661     QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1662     delete object;
1663 }
1664
1665 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1666 {
1667     QString functionSource = QLatin1String("(function(object) { return ") + 
1668                              QLatin1String(source) + QLatin1String(" })");
1669     v8::TryCatch tc;
1670     v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1671     if (tc.HasCaught())
1672         return false;
1673     v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1674     if (function.IsEmpty())
1675         return false;
1676     v8::Handle<v8::Value> args[] = { o };
1677     function->Call(engine->global(), 1, args);
1678     return tc.HasCaught();
1679 }
1680
1681 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o, 
1682                                   const char *source, v8::Handle<v8::Value> result)
1683 {
1684     QString functionSource = QLatin1String("(function(object) { return ") + 
1685                              QLatin1String(source) + QLatin1String(" })");
1686     v8::TryCatch tc;
1687     v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1688     if (tc.HasCaught())
1689         return false;
1690     v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1691     if (function.IsEmpty())
1692         return false;
1693     v8::Handle<v8::Value> args[] = { o };
1694
1695     v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1696
1697     if (tc.HasCaught())
1698         return false;
1699
1700     return value->StrictEquals(result);
1701 }
1702
1703 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o, 
1704                                              const char *source)
1705 {
1706     QString functionSource = QLatin1String("(function(object) { return ") + 
1707                              QLatin1String(source) + QLatin1String(" })");
1708     v8::TryCatch tc;
1709     v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1710     if (tc.HasCaught())
1711         return v8::Handle<v8::Value>();
1712     v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1713     if (function.IsEmpty())
1714         return v8::Handle<v8::Value>();
1715     v8::Handle<v8::Value> args[] = { o };
1716
1717     v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1718
1719     if (tc.HasCaught())
1720         return v8::Handle<v8::Value>();
1721     return value;
1722 }
1723
1724 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1725 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1726 #define EVALUATE(source) evaluate(engine, object, source)
1727
1728 void tst_qdeclarativeecmascript::callQtInvokables()
1729 {
1730     MyInvokableObject o;
1731
1732     QDeclarativeEngine qmlengine;
1733     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1734     
1735     QV8Engine *engine = ep->v8engine();
1736
1737     v8::HandleScope handle_scope;
1738     v8::Context::Scope scope(engine->context());
1739
1740     v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1741
1742     // Non-existent methods
1743     o.reset();
1744     QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1745     QCOMPARE(o.error(), false);
1746     QCOMPARE(o.invoked(), -1);
1747     QCOMPARE(o.actuals().count(), 0);
1748
1749     o.reset();
1750     QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1751     QCOMPARE(o.error(), false);
1752     QCOMPARE(o.invoked(), -1);
1753     QCOMPARE(o.actuals().count(), 0);
1754
1755     // Insufficient arguments
1756     o.reset();
1757     QVERIFY(EVALUATE_ERROR("object.method_int()"));
1758     QCOMPARE(o.error(), false);
1759     QCOMPARE(o.invoked(), -1);
1760     QCOMPARE(o.actuals().count(), 0);
1761
1762     o.reset();
1763     QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1764     QCOMPARE(o.error(), false);
1765     QCOMPARE(o.invoked(), -1);
1766     QCOMPARE(o.actuals().count(), 0);
1767
1768     // Excessive arguments
1769     o.reset();
1770     QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1771     QCOMPARE(o.error(), false);
1772     QCOMPARE(o.invoked(), 8);
1773     QCOMPARE(o.actuals().count(), 1);
1774     QCOMPARE(o.actuals().at(0), QVariant(10));
1775
1776     o.reset();
1777     QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1778     QCOMPARE(o.error(), false);
1779     QCOMPARE(o.invoked(), 9);
1780     QCOMPARE(o.actuals().count(), 2);
1781     QCOMPARE(o.actuals().at(0), QVariant(10));
1782     QCOMPARE(o.actuals().at(1), QVariant(11));
1783
1784     // Test return types
1785     o.reset();
1786     QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1787     QCOMPARE(o.error(), false);
1788     QCOMPARE(o.invoked(), 0);
1789     QCOMPARE(o.actuals().count(), 0);
1790
1791     o.reset();
1792     QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1793     QCOMPARE(o.error(), false);
1794     QCOMPARE(o.invoked(), 1);
1795     QCOMPARE(o.actuals().count(), 0);
1796
1797     o.reset();
1798     QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1799     QCOMPARE(o.error(), false);
1800     QCOMPARE(o.invoked(), 2);
1801     QCOMPARE(o.actuals().count(), 0);
1802
1803     o.reset();
1804     {
1805     v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1806     QVERIFY(!ret.IsEmpty());
1807     QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1808     QCOMPARE(o.error(), false);
1809     QCOMPARE(o.invoked(), 3);
1810     QCOMPARE(o.actuals().count(), 0);
1811     }
1812
1813     o.reset();
1814     {
1815     v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1816     QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1817     QCOMPARE(o.error(), false);
1818     QCOMPARE(o.invoked(), 4);
1819     QCOMPARE(o.actuals().count(), 0);
1820     }
1821
1822     o.reset();
1823     QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1824     QCOMPARE(o.error(), false);
1825     QCOMPARE(o.invoked(), 5);
1826     QCOMPARE(o.actuals().count(), 0);
1827
1828     o.reset();
1829     {
1830     v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1831     QVERIFY(ret->IsString());
1832     QCOMPARE(engine->toString(ret), QString("Hello world"));
1833     QCOMPARE(o.error(), false);
1834     QCOMPARE(o.invoked(), 6);
1835     QCOMPARE(o.actuals().count(), 0);
1836     }
1837
1838     o.reset();
1839     QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1840     QCOMPARE(o.error(), false);
1841     QCOMPARE(o.invoked(), 7);
1842     QCOMPARE(o.actuals().count(), 0);
1843
1844     // Test arg types
1845     o.reset();
1846     QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1847     QCOMPARE(o.error(), false);
1848     QCOMPARE(o.invoked(), 8);
1849     QCOMPARE(o.actuals().count(), 1);
1850     QCOMPARE(o.actuals().at(0), QVariant(94));
1851
1852     o.reset();
1853     QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1854     QCOMPARE(o.error(), false);
1855     QCOMPARE(o.invoked(), 8);
1856     QCOMPARE(o.actuals().count(), 1);
1857     QCOMPARE(o.actuals().at(0), QVariant(94));
1858
1859     o.reset();
1860     QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1861     QCOMPARE(o.error(), false);
1862     QCOMPARE(o.invoked(), 8);
1863     QCOMPARE(o.actuals().count(), 1);
1864     QCOMPARE(o.actuals().at(0), QVariant(0));
1865
1866     o.reset();
1867     QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1868     QCOMPARE(o.error(), false);
1869     QCOMPARE(o.invoked(), 8);
1870     QCOMPARE(o.actuals().count(), 1);
1871     QCOMPARE(o.actuals().at(0), QVariant(0));
1872
1873     o.reset();
1874     QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1875     QCOMPARE(o.error(), false);
1876     QCOMPARE(o.invoked(), 8);
1877     QCOMPARE(o.actuals().count(), 1);
1878     QCOMPARE(o.actuals().at(0), QVariant(0));
1879
1880     o.reset();
1881     QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1882     QCOMPARE(o.error(), false);
1883     QCOMPARE(o.invoked(), 8);
1884     QCOMPARE(o.actuals().count(), 1);
1885     QCOMPARE(o.actuals().at(0), QVariant(0));
1886
1887     o.reset();
1888     QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1889     QCOMPARE(o.error(), false);
1890     QCOMPARE(o.invoked(), 9);
1891     QCOMPARE(o.actuals().count(), 2);
1892     QCOMPARE(o.actuals().at(0), QVariant(122));
1893     QCOMPARE(o.actuals().at(1), QVariant(9));
1894
1895     o.reset();
1896     QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1897     QCOMPARE(o.error(), false);
1898     QCOMPARE(o.invoked(), 10);
1899     QCOMPARE(o.actuals().count(), 1);
1900     QCOMPARE(o.actuals().at(0), QVariant(94.3));
1901
1902     o.reset();
1903     QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1904     QCOMPARE(o.error(), false);
1905     QCOMPARE(o.invoked(), 10);
1906     QCOMPARE(o.actuals().count(), 1);
1907     QCOMPARE(o.actuals().at(0), QVariant(94.3));
1908
1909     o.reset();
1910     QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1911     QCOMPARE(o.error(), false);
1912     QCOMPARE(o.invoked(), 10);
1913     QCOMPARE(o.actuals().count(), 1);
1914     QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1915
1916     o.reset();
1917     QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1918     QCOMPARE(o.error(), false);
1919     QCOMPARE(o.invoked(), 10);
1920     QCOMPARE(o.actuals().count(), 1);
1921     QCOMPARE(o.actuals().at(0), QVariant(0));
1922
1923     o.reset();
1924     QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1925     QCOMPARE(o.error(), false);
1926     QCOMPARE(o.invoked(), 10);
1927     QCOMPARE(o.actuals().count(), 1);
1928     QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1929
1930     o.reset();
1931     QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1932     QCOMPARE(o.error(), false);
1933     QCOMPARE(o.invoked(), 10);
1934     QCOMPARE(o.actuals().count(), 1);
1935     QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1936
1937     o.reset();
1938     QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1939     QCOMPARE(o.error(), false);
1940     QCOMPARE(o.invoked(), 11);
1941     QCOMPARE(o.actuals().count(), 1);
1942     QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1943
1944     o.reset();
1945     QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1946     QCOMPARE(o.error(), false);
1947     QCOMPARE(o.invoked(), 11);
1948     QCOMPARE(o.actuals().count(), 1);
1949     QCOMPARE(o.actuals().at(0), QVariant("19"));
1950
1951     o.reset();
1952     {
1953     QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1954     QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1955     QCOMPARE(o.error(), false);
1956     QCOMPARE(o.invoked(), 11);
1957     QCOMPARE(o.actuals().count(), 1);
1958     QCOMPARE(o.actuals().at(0), QVariant(expected));
1959     }
1960
1961     o.reset();
1962     QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1963     QCOMPARE(o.error(), false);
1964     QCOMPARE(o.invoked(), 11);
1965     QCOMPARE(o.actuals().count(), 1);
1966     QCOMPARE(o.actuals().at(0), QVariant(QString()));
1967
1968     o.reset();
1969     QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1970     QCOMPARE(o.error(), false);
1971     QCOMPARE(o.invoked(), 11);
1972     QCOMPARE(o.actuals().count(), 1);
1973     QCOMPARE(o.actuals().at(0), QVariant(QString()));
1974
1975     o.reset();
1976     QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1977     QCOMPARE(o.error(), false);
1978     QCOMPARE(o.invoked(), 12);
1979     QCOMPARE(o.actuals().count(), 1);
1980     QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1981
1982     o.reset();
1983     QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1984     QCOMPARE(o.error(), false);
1985     QCOMPARE(o.invoked(), 12);
1986     QCOMPARE(o.actuals().count(), 1);
1987     QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1988
1989     o.reset();
1990     QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1991     QCOMPARE(o.error(), false);
1992     QCOMPARE(o.invoked(), 12);
1993     QCOMPARE(o.actuals().count(), 1);
1994     QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1995
1996     o.reset();
1997     QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1998     QCOMPARE(o.error(), false);
1999     QCOMPARE(o.invoked(), 12);
2000     QCOMPARE(o.actuals().count(), 1);
2001     QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2002
2003     o.reset();
2004     QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
2005     QCOMPARE(o.error(), false);
2006     QCOMPARE(o.invoked(), 12);
2007     QCOMPARE(o.actuals().count(), 1);
2008     QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
2009
2010     o.reset();
2011     QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
2012     QCOMPARE(o.error(), false);
2013     QCOMPARE(o.invoked(), 12);
2014     QCOMPARE(o.actuals().count(), 1);
2015     QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
2016
2017     o.reset();
2018     QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
2019     QCOMPARE(o.error(), false);
2020     QCOMPARE(o.invoked(), 13);
2021     QCOMPARE(o.actuals().count(), 1);
2022     QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2023
2024     o.reset();
2025     QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
2026     QCOMPARE(o.error(), false);
2027     QCOMPARE(o.invoked(), 13);
2028     QCOMPARE(o.actuals().count(), 1);
2029     QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2030
2031     o.reset();
2032     QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
2033     QCOMPARE(o.error(), false);
2034     QCOMPARE(o.invoked(), 13);
2035     QCOMPARE(o.actuals().count(), 1);
2036     QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2037
2038     o.reset();
2039     QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
2040     QCOMPARE(o.error(), false);
2041     QCOMPARE(o.invoked(), 13);
2042     QCOMPARE(o.actuals().count(), 1);
2043     QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2044
2045     o.reset();
2046     QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
2047     QCOMPARE(o.error(), false);
2048     QCOMPARE(o.invoked(), 13);
2049     QCOMPARE(o.actuals().count(), 1);
2050     QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
2051
2052     o.reset();
2053     QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
2054     QCOMPARE(o.error(), false);
2055     QCOMPARE(o.invoked(), 14);
2056     QCOMPARE(o.actuals().count(), 1);
2057     QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
2058
2059     o.reset();
2060     QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
2061     QCOMPARE(o.error(), false);
2062     QCOMPARE(o.invoked(), 14);
2063     QCOMPARE(o.actuals().count(), 1);
2064     QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
2065
2066     o.reset();
2067     QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
2068     QCOMPARE(o.error(), false);
2069     QCOMPARE(o.invoked(), 14);
2070     QCOMPARE(o.actuals().count(), 1);
2071     QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
2072
2073     o.reset();
2074     QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
2075     QCOMPARE(o.error(), false);
2076     QCOMPARE(o.invoked(), 14);
2077     QCOMPARE(o.actuals().count(), 1);
2078     QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
2079
2080     o.reset();
2081     QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
2082     QCOMPARE(o.error(), false);
2083     QCOMPARE(o.invoked(), 15);
2084     QCOMPARE(o.actuals().count(), 2);
2085     QCOMPARE(o.actuals().at(0), QVariant(4));
2086     QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
2087
2088     o.reset();
2089     QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
2090     QCOMPARE(o.error(), false);
2091     QCOMPARE(o.invoked(), 15);
2092     QCOMPARE(o.actuals().count(), 2);
2093     QCOMPARE(o.actuals().at(0), QVariant(8));
2094     QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
2095
2096     o.reset();
2097     QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
2098     QCOMPARE(o.error(), false);
2099     QCOMPARE(o.invoked(), 15);
2100     QCOMPARE(o.actuals().count(), 2);
2101     QCOMPARE(o.actuals().at(0), QVariant(3));
2102     QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
2103
2104     o.reset();
2105     QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
2106     QCOMPARE(o.error(), false);
2107     QCOMPARE(o.invoked(), 15);
2108     QCOMPARE(o.actuals().count(), 2);
2109     QCOMPARE(o.actuals().at(0), QVariant(44));
2110     QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
2111
2112     o.reset();
2113     QVERIFY(EVALUATE_ERROR("object.method_overload()"));
2114     QCOMPARE(o.error(), false);
2115     QCOMPARE(o.invoked(), -1);
2116     QCOMPARE(o.actuals().count(), 0);
2117
2118     o.reset();
2119     QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
2120     QCOMPARE(o.error(), false);
2121     QCOMPARE(o.invoked(), 16);
2122     QCOMPARE(o.actuals().count(), 1);
2123     QCOMPARE(o.actuals().at(0), QVariant(10));
2124
2125     o.reset();
2126     QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
2127     QCOMPARE(o.error(), false);
2128     QCOMPARE(o.invoked(), 17);
2129     QCOMPARE(o.actuals().count(), 2);
2130     QCOMPARE(o.actuals().at(0), QVariant(10));
2131     QCOMPARE(o.actuals().at(1), QVariant(11));
2132
2133     o.reset();
2134     QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2135     QCOMPARE(o.error(), false);
2136     QCOMPARE(o.invoked(), 18);
2137     QCOMPARE(o.actuals().count(), 1);
2138     QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2139
2140     o.reset();
2141     QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2142     QCOMPARE(o.error(), false);
2143     QCOMPARE(o.invoked(), 19);
2144     QCOMPARE(o.actuals().count(), 1);
2145     QCOMPARE(o.actuals().at(0), QVariant(9));
2146
2147     o.reset();
2148     QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2149     QCOMPARE(o.error(), false);
2150     QCOMPARE(o.invoked(), 20);
2151     QCOMPARE(o.actuals().count(), 2);
2152     QCOMPARE(o.actuals().at(0), QVariant(10));
2153     QCOMPARE(o.actuals().at(1), QVariant(19));
2154
2155     o.reset();
2156     QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2157     QCOMPARE(o.error(), false);
2158     QCOMPARE(o.invoked(), 20);
2159     QCOMPARE(o.actuals().count(), 2);
2160     QCOMPARE(o.actuals().at(0), QVariant(10));
2161     QCOMPARE(o.actuals().at(1), QVariant(13));
2162
2163     o.reset();
2164     QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2165     QCOMPARE(o.error(), false);
2166     QCOMPARE(o.invoked(), -3);
2167     QCOMPARE(o.actuals().count(), 1);
2168     QCOMPARE(o.actuals().at(0), QVariant(9));
2169
2170     o.reset();
2171     QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2172     QCOMPARE(o.error(), false);
2173     QCOMPARE(o.invoked(), 21);
2174     QCOMPARE(o.actuals().count(), 2);
2175     QCOMPARE(o.actuals().at(0), QVariant(9));
2176     QCOMPARE(o.actuals().at(1), QVariant());
2177
2178     o.reset();
2179     QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2180     QCOMPARE(o.error(), false);
2181     QCOMPARE(o.invoked(), 21);
2182     QCOMPARE(o.actuals().count(), 2);
2183     QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2184     QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2185 }
2186
2187 // QTBUG-13047 (check that you can pass registered object types as args)
2188 void tst_qdeclarativeecmascript::invokableObjectArg()
2189 {
2190     QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2191
2192     QObject *o = component.create();
2193     QVERIFY(o);
2194     MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2195     QVERIFY(qmlobject);
2196     QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2197
2198     delete o;
2199 }
2200
2201 // QTBUG-13047 (check that you can return registered object types from methods)
2202 void tst_qdeclarativeecmascript::invokableObjectRet()
2203 {
2204     QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2205
2206     QObject *o = component.create();
2207     QVERIFY(o);
2208     QCOMPARE(o->property("test").toBool(), true);
2209     delete o;
2210 }
2211
2212 // QTBUG-5675
2213 void tst_qdeclarativeecmascript::listToVariant()
2214 {
2215     QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2216
2217     MyQmlContainer container;
2218
2219     QDeclarativeContext context(engine.rootContext());
2220     context.setContextObject(&container);
2221
2222     QObject *object = component.create(&context);
2223     QVERIFY(object != 0);
2224
2225     QVariant v = object->property("test");
2226     QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2227     QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2228
2229     delete object;
2230 }
2231
2232 // QTBUG-7957
2233 void tst_qdeclarativeecmascript::multiEngineObject()
2234 {
2235     MyQmlObject obj;
2236     obj.setStringProperty("Howdy planet");
2237
2238     QDeclarativeEngine e1;
2239     e1.rootContext()->setContextProperty("thing", &obj);
2240     QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2241
2242     QDeclarativeEngine e2;
2243     e2.rootContext()->setContextProperty("thing", &obj);
2244     QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2245
2246     QObject *o1 = c1.create();
2247     QObject *o2 = c2.create();
2248
2249     QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2250     QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2251
2252     delete o2;
2253     delete o1;
2254 }
2255
2256 // Test that references to QObjects are cleanup when the object is destroyed
2257 void tst_qdeclarativeecmascript::deletedObject()
2258 {
2259     QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2260
2261     QObject *object = component.create();
2262
2263     QCOMPARE(object->property("test1").toBool(), true);
2264     QCOMPARE(object->property("test2").toBool(), true);
2265     QCOMPARE(object->property("test3").toBool(), true);
2266     QCOMPARE(object->property("test4").toBool(), true);
2267
2268     delete object;
2269 }
2270
2271 void tst_qdeclarativeecmascript::attachedPropertyScope()
2272 {
2273     QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2274
2275     QObject *object = component.create();
2276     QVERIFY(object != 0);
2277
2278     MyQmlAttachedObject *attached = 
2279         qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2280     QVERIFY(attached != 0);
2281
2282     QCOMPARE(object->property("value2").toInt(), 0);
2283
2284     attached->emitMySignal();
2285
2286     QCOMPARE(object->property("value2").toInt(), 9);
2287
2288     delete object;
2289 }
2290
2291 void tst_qdeclarativeecmascript::scriptConnect()
2292 {
2293     {
2294         QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2295
2296         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2297         QVERIFY(object != 0);
2298
2299         QCOMPARE(object->property("test").toBool(), false);
2300         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2301         QCOMPARE(object->property("test").toBool(), true);
2302
2303         delete object;
2304     }
2305
2306     {
2307         QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2308
2309         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2310         QVERIFY(object != 0);
2311
2312         QCOMPARE(object->property("test").toBool(), false);
2313         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2314         QCOMPARE(object->property("test").toBool(), true);
2315
2316         delete object;
2317     }
2318
2319     {
2320         QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2321
2322         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2323         QVERIFY(object != 0);
2324
2325         QCOMPARE(object->property("test").toBool(), false);
2326         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2327         QCOMPARE(object->property("test").toBool(), true);
2328
2329         delete object;
2330     }
2331
2332     {
2333         QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2334
2335         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2336         QVERIFY(object != 0);
2337
2338         QCOMPARE(object->methodCalled(), false);
2339         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2340         QCOMPARE(object->methodCalled(), true);
2341
2342         delete object;
2343     }
2344
2345     {
2346         QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2347
2348         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2349         QVERIFY(object != 0);
2350
2351         QCOMPARE(object->methodCalled(), false);
2352         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2353         QCOMPARE(object->methodCalled(), true);
2354
2355         delete object;
2356     }
2357
2358     {
2359         QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2360
2361         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2362         QVERIFY(object != 0);
2363
2364         QCOMPARE(object->property("test").toInt(), 0);
2365         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2366         QCOMPARE(object->property("test").toInt(), 2);
2367
2368         delete object;
2369     }
2370 }
2371
2372 void tst_qdeclarativeecmascript::scriptDisconnect()
2373 {
2374     {
2375         QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2376
2377         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2378         QVERIFY(object != 0);
2379
2380         QCOMPARE(object->property("test").toInt(), 0);
2381         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2382         QCOMPARE(object->property("test").toInt(), 1);
2383         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2384         QCOMPARE(object->property("test").toInt(), 2);
2385         emit object->basicSignal();
2386         QCOMPARE(object->property("test").toInt(), 2);
2387         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2388         QCOMPARE(object->property("test").toInt(), 2);
2389
2390         delete object;
2391     }
2392
2393     {
2394         QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2395
2396         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2397         QVERIFY(object != 0);
2398
2399         QCOMPARE(object->property("test").toInt(), 0);
2400         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2401         QCOMPARE(object->property("test").toInt(), 1);
2402         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2403         QCOMPARE(object->property("test").toInt(), 2);
2404         emit object->basicSignal();
2405         QCOMPARE(object->property("test").toInt(), 2);
2406         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2407         QCOMPARE(object->property("test").toInt(), 2);
2408
2409         delete object;
2410     }
2411
2412     {
2413         QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2414
2415         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2416         QVERIFY(object != 0);
2417
2418         QCOMPARE(object->property("test").toInt(), 0);
2419         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2420         QCOMPARE(object->property("test").toInt(), 1);
2421         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2422         QCOMPARE(object->property("test").toInt(), 2);
2423         emit object->basicSignal();
2424         QCOMPARE(object->property("test").toInt(), 2);
2425         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2426         QCOMPARE(object->property("test").toInt(), 3);
2427
2428         delete object;
2429     }
2430     {
2431         QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2432
2433         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2434         QVERIFY(object != 0);
2435
2436         QCOMPARE(object->property("test").toInt(), 0);
2437         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2438         QCOMPARE(object->property("test").toInt(), 1);
2439         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2440         QCOMPARE(object->property("test").toInt(), 2);
2441         emit object->basicSignal();
2442         QCOMPARE(object->property("test").toInt(), 2);
2443         emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2444         QCOMPARE(object->property("test").toInt(), 3);
2445
2446         delete object;
2447     }
2448 }
2449
2450 class OwnershipObject : public QObject
2451 {
2452     Q_OBJECT
2453 public:
2454     OwnershipObject() { object = new QObject; }
2455
2456     QPointer<QObject> object;
2457
2458 public slots:
2459     QObject *getObject() { return object; }
2460 };
2461
2462 void tst_qdeclarativeecmascript::ownership()
2463 {
2464     OwnershipObject own;
2465     QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2466     context->setContextObject(&own);
2467
2468     {
2469         QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2470
2471         QVERIFY(own.object != 0);
2472
2473         QObject *object = component.create(context);
2474
2475         engine.collectGarbage();
2476
2477         QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2478
2479         QVERIFY(own.object == 0);
2480
2481         delete object;
2482     }
2483
2484     own.object = new QObject(&own);
2485
2486     {
2487         QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2488
2489         QVERIFY(own.object != 0);
2490
2491         QObject *object = component.create(context);
2492         
2493         engine.collectGarbage();
2494
2495         QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2496
2497         QVERIFY(own.object != 0);
2498
2499         delete object;
2500     }
2501
2502     delete context;
2503 }
2504
2505 class CppOwnershipReturnValue : public QObject
2506 {
2507     Q_OBJECT
2508 public:
2509     CppOwnershipReturnValue() : value(0) {}
2510     ~CppOwnershipReturnValue() { delete value; }
2511
2512     Q_INVOKABLE QObject *create() {
2513         value = new QObject;
2514         QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2515         return value;
2516     }
2517
2518     Q_INVOKABLE MyQmlObject *createQmlObject() {
2519         MyQmlObject *rv = new MyQmlObject;
2520         value = rv;
2521         return rv;
2522     }
2523
2524     QPointer<QObject> value;
2525 };
2526
2527 // QTBUG-15695.  
2528 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2529 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2530 {
2531     CppOwnershipReturnValue source;
2532
2533     {
2534     QDeclarativeEngine engine;
2535     engine.rootContext()->setContextProperty("source", &source);
2536
2537     QVERIFY(source.value == 0);
2538
2539     QDeclarativeComponent component(&engine);
2540     component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2541
2542     QObject *object = component.create();
2543
2544     QVERIFY(object != 0);
2545     QVERIFY(source.value != 0);
2546
2547     delete object;
2548     }
2549
2550     QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2551
2552     QVERIFY(source.value != 0);
2553 }
2554
2555 // QTBUG-15697
2556 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2557 {
2558     CppOwnershipReturnValue source;
2559
2560     {
2561     QDeclarativeEngine engine;
2562     engine.rootContext()->setContextProperty("source", &source);
2563
2564     QVERIFY(source.value == 0);
2565
2566     QDeclarativeComponent component(&engine);
2567     component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2568
2569     QObject *object = component.create();
2570
2571     QVERIFY(object != 0);
2572     QVERIFY(source.value != 0);
2573
2574     delete object;
2575     }
2576
2577     engine.collectGarbage();
2578     QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2579
2580     QVERIFY(source.value == 0);
2581 }
2582
2583 class QListQObjectMethodsObject : public QObject
2584 {
2585     Q_OBJECT
2586 public:
2587     QListQObjectMethodsObject() {
2588         m_objects.append(new MyQmlObject());
2589         m_objects.append(new MyQmlObject());
2590     }
2591
2592     ~QListQObjectMethodsObject() {
2593         qDeleteAll(m_objects);
2594     }
2595
2596 public slots:
2597     QList<QObject *> getObjects() { return m_objects; }
2598
2599 private:
2600     QList<QObject *> m_objects;
2601 };
2602
2603 // Tests that returning a QList<QObject*> from a method works
2604 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2605 {
2606     QListQObjectMethodsObject obj;
2607     QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2608     context->setContextObject(&obj);
2609
2610     QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2611
2612     QObject *object = component.create(context);
2613
2614     QCOMPARE(object->property("test").toInt(), 2);
2615     QCOMPARE(object->property("test2").toBool(), true);
2616
2617     delete object;
2618     delete context;
2619 }
2620
2621 // QTBUG-9205
2622 void tst_qdeclarativeecmascript::strictlyEquals()
2623 {
2624     QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2625
2626     QObject *object = component.create();
2627     QVERIFY(object != 0);
2628
2629     QCOMPARE(object->property("test1").toBool(), true);
2630     QCOMPARE(object->property("test2").toBool(), true);
2631     QCOMPARE(object->property("test3").toBool(), true);
2632     QCOMPARE(object->property("test4").toBool(), true);
2633     QCOMPARE(object->property("test5").toBool(), true);
2634     QCOMPARE(object->property("test6").toBool(), true);
2635     QCOMPARE(object->property("test7").toBool(), true);
2636     QCOMPARE(object->property("test8").toBool(), true);
2637
2638     delete object;
2639 }
2640
2641 void tst_qdeclarativeecmascript::compiled()
2642 {
2643     QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2644
2645     QObject *object = component.create();
2646     QVERIFY(object != 0);
2647
2648     QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2649     QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2650     QCOMPARE(object->property("test3").toBool(), true);
2651     QCOMPARE(object->property("test4").toBool(), false);
2652     QCOMPARE(object->property("test5").toBool(), false);
2653     QCOMPARE(object->property("test6").toBool(), true);
2654
2655     QCOMPARE(object->property("test7").toInt(), 185);
2656     QCOMPARE(object->property("test8").toInt(), 167);
2657     QCOMPARE(object->property("test9").toBool(), true);
2658     QCOMPARE(object->property("test10").toBool(), false);
2659     QCOMPARE(object->property("test11").toBool(), false);
2660     QCOMPARE(object->property("test12").toBool(), true);
2661
2662     QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2663     QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2664     QCOMPARE(object->property("test15").toBool(), false);
2665     QCOMPARE(object->property("test16").toBool(), true);
2666
2667     QCOMPARE(object->property("test17").toInt(), 5);
2668     QCOMPARE(object->property("test18").toReal(), qreal(176));
2669     QCOMPARE(object->property("test19").toInt(), 7);
2670     QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2671     QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2672     QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2673     QCOMPARE(object->property("test23").toBool(), true);
2674     QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2675     QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2676
2677     delete object;
2678 }
2679
2680 // Test that numbers assigned in bindings as strings work consistently
2681 void tst_qdeclarativeecmascript::numberAssignment()
2682 {
2683     QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2684
2685     QObject *object = component.create();
2686     QVERIFY(object != 0);
2687
2688     QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2689     QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2690     QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2691     QCOMPARE(object->property("test3"), QVariant((qreal)6));
2692     QCOMPARE(object->property("test4"), QVariant((qreal)6));
2693
2694     QCOMPARE(object->property("test5"), QVariant((int)7));
2695     QCOMPARE(object->property("test6"), QVariant((int)7));
2696     QCOMPARE(object->property("test7"), QVariant((int)6));
2697     QCOMPARE(object->property("test8"), QVariant((int)6));
2698
2699     QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2700     QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2701     QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2702     QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2703
2704     delete object;
2705 }
2706
2707 void tst_qdeclarativeecmascript::propertySplicing()
2708 {
2709     QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2710
2711     QObject *object = component.create();
2712     QVERIFY(object != 0);
2713
2714     QCOMPARE(object->property("test").toBool(), true);
2715
2716     delete object;
2717 }
2718
2719 // QTBUG-16683
2720 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2721 {
2722     QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2723
2724     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2725     QVERIFY(object != 0);
2726
2727     MyQmlObject::MyType type;
2728     type.value = 0x8971123;
2729     emit object->signalWithUnknownType(type);
2730
2731     MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2732
2733     QCOMPARE(result.value, type.value);
2734
2735
2736     delete object;
2737 }
2738
2739 void tst_qdeclarativeecmascript::moduleApi_data()
2740 {
2741     QTest::addColumn<QUrl>("testfile");
2742     QTest::addColumn<QString>("errorMessage");
2743     QTest::addColumn<QStringList>("warningMessages");
2744     QTest::addColumn<QStringList>("readProperties");
2745     QTest::addColumn<QVariantList>("readExpectedValues");
2746     QTest::addColumn<QStringList>("writeProperties");
2747     QTest::addColumn<QVariantList>("writeValues");
2748     QTest::addColumn<QStringList>("readBackProperties");
2749     QTest::addColumn<QVariantList>("readBackExpectedValues");
2750
2751     QTest::newRow("qobject, register + read + method")
2752             << TEST_FILE("moduleapi/qobjectModuleApi.qml")
2753             << QString()
2754             << QStringList()
2755             << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest"
2756                    << "qobjectMinorVersionTest" << "qobjectMajorVersionTest" << "qobjectParentedTest")
2757             << (QVariantList() << 20 << 20 << 1 << 20 << 20 << 26)
2758             << QStringList()
2759             << QVariantList()
2760             << QStringList()
2761             << QVariantList();
2762
2763     QTest::newRow("script, register + read")
2764             << TEST_FILE("moduleapi/scriptModuleApi.qml")
2765             << QString()
2766             << QStringList()
2767             << (QStringList() << "scriptTest")
2768             << (QVariantList() << 13)
2769             << QStringList()
2770             << QVariantList()
2771             << QStringList()
2772             << QVariantList();
2773
2774     QTest::newRow("qobject, caching + read")
2775             << TEST_FILE("moduleapi/qobjectModuleApiCaching.qml")
2776             << QString()
2777             << QStringList()
2778             << (QStringList() << "existingUriTest" << "qobjectParentedTest")
2779             << (QVariantList() << 20 << 26) // 26, shouldn't have incremented to 27.
2780             << QStringList()
2781             << QVariantList()
2782             << QStringList()
2783             << QVariantList();
2784
2785     QTest::newRow("script, caching + read")
2786             << TEST_FILE("moduleapi/scriptModuleApiCaching.qml")
2787             << QString()
2788             << QStringList()
2789             << (QStringList() << "scriptTest")
2790             << (QVariantList() << 13) // 13, shouldn't have incremented to 14.
2791             << QStringList()
2792             << QVariantList()
2793             << QStringList()
2794             << QVariantList();
2795
2796     QTest::newRow("qobject, writing + readonly constraints")
2797             << TEST_FILE("moduleapi/qobjectModuleApiWriting.qml")
2798             << QString()
2799             << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":14: Error: Cannot assign to read-only property \"qobjectTestProperty\"")))
2800             << (QStringList() << "readOnlyProperty" << "writableProperty")
2801             << (QVariantList() << 20 << 50)
2802             << (QStringList() << "firstProperty" << "writableProperty")
2803             << (QVariantList() << 30 << 30)
2804             << (QStringList() << "readOnlyProperty" << "writableProperty")
2805             << (QVariantList() << 20 << 30);
2806
2807     QTest::newRow("script, writing + readonly constraints")
2808             << TEST_FILE("moduleapi/scriptModuleApiWriting.qml")
2809             << QString()
2810             << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/scriptModuleApiWriting.qml").toLocalFile() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\"")))
2811             << (QStringList() << "readBack" << "unchanged")
2812             << (QVariantList() << 13 << 42)
2813             << (QStringList() << "firstProperty" << "secondProperty")
2814             << (QVariantList() << 30 << 30)
2815             << (QStringList() << "readBack" << "unchanged")
2816             << (QVariantList() << 30 << 42);
2817
2818     QTest::newRow("qobject, invalid major version fail")
2819             << TEST_FILE("moduleapi/moduleApiMajorVersionFail.qml")
2820             << QString("QDeclarativeComponent: Component is not ready")
2821             << QStringList()
2822             << QStringList()
2823             << QVariantList()
2824             << QStringList()
2825             << QVariantList()
2826             << QStringList()
2827             << QVariantList();
2828
2829     QTest::newRow("qobject, invalid minor version fail")
2830             << TEST_FILE("moduleapi/moduleApiMinorVersionFail.qml")
2831             << QString("QDeclarativeComponent: Component is not ready")
2832             << QStringList()
2833             << QStringList()
2834             << QVariantList()
2835             << QStringList()
2836             << QVariantList()
2837             << QStringList()
2838             << QVariantList();
2839 }
2840
2841 void tst_qdeclarativeecmascript::moduleApi()
2842 {
2843     QFETCH(QUrl, testfile);
2844     QFETCH(QString, errorMessage);
2845     QFETCH(QStringList, warningMessages);
2846     QFETCH(QStringList, readProperties);
2847     QFETCH(QVariantList, readExpectedValues);
2848     QFETCH(QStringList, writeProperties);
2849     QFETCH(QVariantList, writeValues);
2850     QFETCH(QStringList, readBackProperties);
2851     QFETCH(QVariantList, readBackExpectedValues);
2852
2853     QDeclarativeComponent component(&engine, testfile);
2854
2855     if (!errorMessage.isEmpty())
2856         QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData());
2857
2858     if (warningMessages.size())
2859         foreach (const QString &warning, warningMessages)
2860             QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
2861
2862     QObject *object = component.create();
2863     if (!errorMessage.isEmpty()) {
2864         QVERIFY(object == 0);
2865     } else {
2866         QVERIFY(object != 0);
2867         for (int i = 0; i < readProperties.size(); ++i)
2868             QCOMPARE(object->property(readProperties.at(i).toAscii().constData()), readExpectedValues.at(i));
2869         for (int i = 0; i < writeProperties.size(); ++i)
2870             QVERIFY(object->setProperty(writeProperties.at(i).toAscii().constData(), writeValues.at(i)));
2871         for (int i = 0; i < readBackProperties.size(); ++i)
2872             QCOMPARE(object->property(readBackProperties.at(i).toAscii().constData()), readBackExpectedValues.at(i));
2873         delete object;
2874     }
2875 }
2876
2877 void tst_qdeclarativeecmascript::importScripts()
2878 {
2879     QObject *object = 0;
2880
2881     // first, ensure that the required behaviour works.
2882     QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2883     object = component.create();
2884     QVERIFY(object != 0);
2885     QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2886     QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2887     QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2888     QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2889     delete object;
2890
2891     QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2892     object = componentTwo.create();
2893     QVERIFY(object != 0);
2894     QCOMPARE(object->property("componentError"), QVariant(5));
2895     delete object;
2896
2897     // then, ensure that unintended behaviour does not work.
2898     QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2899     QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2900     QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2901     object = failOneComponent.create();
2902     QVERIFY(object != 0);
2903     QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2904     delete object;
2905     QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2906     expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2907     QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2908     object = failTwoComponent.create();
2909     QVERIFY(object != 0);
2910     QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2911     delete object;
2912     QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2913     expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2914     QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2915     object = failThreeComponent.create();
2916     QVERIFY(object != 0);
2917     QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2918     delete object;
2919     QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2920     expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2921     QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2922     object = failFourComponent.create();
2923     QVERIFY(object != 0);
2924     QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2925     delete object;
2926     QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2927     expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2928     QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2929     expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2930     QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2931     object = failFiveComponent.create();
2932     QVERIFY(object != 0);
2933     QCOMPARE(object->property("componentError"), QVariant(0));
2934     delete object;
2935
2936     // also, test that importing scripts with .pragma library works as required
2937     QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2938     object = pragmaLibraryComponent.create();
2939     QVERIFY(object != 0);
2940     QCOMPARE(object->property("testValue"), QVariant(31));
2941     delete object;
2942
2943     // and that .pragma library scripts don't inherit imports from any .qml file
2944     QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2945     object = pragmaLibraryComponentTwo.create();
2946     QVERIFY(object != 0);
2947     QCOMPARE(object->property("testValue"), QVariant(0));
2948     delete object;
2949 }
2950
2951 void tst_qdeclarativeecmascript::scarceResources()
2952 {
2953     QPixmap origPixmap(100, 100);
2954     origPixmap.fill(Qt::blue);
2955
2956     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2957     ScarceResourceObject *eo = 0;
2958     QObject *object = 0;
2959
2960     // in the following three cases, the instance created from the component
2961     // has a property which is a copy of the scarce resource; hence, the
2962     // resource should NOT be detached prior to deletion of the object instance,
2963     // unless the resource is destroyed explicitly.
2964     QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2965     object = component.create();
2966     QVERIFY(object != 0);
2967     QVERIFY(object->property("scarceResourceCopy").isValid());
2968     QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2969     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2970     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2971     QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2972     delete object;
2973
2974     QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2975     object = componentTwo.create();
2976     QVERIFY(object != 0);
2977     QVERIFY(object->property("scarceResourceCopy").isValid());
2978     QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2979     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2980     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2981     QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2982     delete object;
2983
2984     QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2985     object = componentThree.create();
2986     QVERIFY(object != 0);
2987     QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2988     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2989     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2990     QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2991     delete object;
2992
2993     // in the following three cases, no other copy should exist in memory,
2994     // and so it should be detached (unless explicitly preserved).
2995     QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2996     object = componentFour.create();
2997     QVERIFY(object != 0);
2998     QVERIFY(object->property("scarceResourceTest").isValid());
2999     QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3000     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3001     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3002     QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
3003     delete object;
3004
3005     QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
3006     object = componentFive.create();
3007     QVERIFY(object != 0);
3008     QVERIFY(object->property("scarceResourceTest").isValid());
3009     QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3010     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3011     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3012     QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
3013     delete object;
3014
3015     QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
3016     object = componentSix.create();
3017     QVERIFY(object != 0);
3018     QVERIFY(object->property("scarceResourceTest").isValid());
3019     QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3020     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3021     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3022     QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
3023     delete object;
3024
3025     // test that scarce resources are handled correctly for imports
3026     QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
3027     object = componentSeven.create();
3028     QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
3029     QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
3030     delete object;
3031
3032     QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
3033     object = componentEight.create();
3034     QVERIFY(object != 0);
3035     QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
3036     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3037     delete object;
3038
3039     QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
3040     object = componentNine.create();
3041     QVERIFY(object != 0);
3042     QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
3043     QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3044     QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
3045     QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
3046     QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
3047     QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
3048     delete object;
3049
3050     // test that scarce resources are handled properly in signal invocation
3051     QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
3052     object = componentTen.create();
3053     QVERIFY(object != 0);
3054     QObject *srsc = object->findChild<QObject*>("srsc");
3055     QVERIFY(srsc);
3056     QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
3057     QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
3058     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3059     QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3060     QMetaObject::invokeMethod(srsc, "testSignal");
3061     QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
3062     QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
3063     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3064     QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
3065     QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
3066     QVERIFY(srsc->property("scarceResourceCopy").isValid());
3067     QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3068     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3069     QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
3070     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3071     delete object;
3072
3073     // test that scarce resources are handled properly from js functions in qml files
3074     QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
3075     object = componentEleven.create();
3076     QVERIFY(object != 0);
3077     QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3078     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3079     QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3080     QMetaObject::invokeMethod(object, "retrieveScarceResource");
3081     QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
3082     QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3083     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3084     QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
3085     QMetaObject::invokeMethod(object, "releaseScarceResource");
3086     QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
3087     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3088     QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3089     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3090     delete object;
3091
3092     // test that if an exception occurs while invoking js function from cpp, that the resources are released.
3093     QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
3094     object = componentTwelve.create();
3095     QVERIFY(object != 0);
3096     QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3097     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3098     QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3099     QString srp_name = object->property("srp_name").toString();
3100     QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
3101     QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
3102     QMetaObject::invokeMethod(object, "retrieveScarceResource");
3103     QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
3104     eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3105     QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3106     QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3107     delete object;
3108 }
3109
3110 void tst_qdeclarativeecmascript::propertyChangeSlots()
3111 {
3112     // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
3113     QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
3114     QObject *object = component.create();
3115     QVERIFY(object != 0);
3116     delete object;
3117
3118     // ensure that invalid property names fail properly.
3119     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3120     QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
3121     QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
3122     QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
3123     object = e1.create();
3124     QVERIFY(object == 0);
3125     delete object;
3126
3127     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3128     QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
3129     expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
3130     QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
3131     object = e2.create();
3132     QVERIFY(object == 0);
3133     delete object;
3134
3135     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3136     QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
3137     expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
3138     QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
3139     object = e3.create();
3140     QVERIFY(object == 0);
3141     delete object;
3142
3143     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3144     QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
3145     expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
3146     QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
3147     object = e4.create();
3148     QVERIFY(object == 0);
3149     delete object;
3150 }
3151
3152 // Ensure that QObject type conversion works on binding assignment
3153 void tst_qdeclarativeecmascript::elementAssign()
3154 {
3155     QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
3156
3157     QObject *object = component.create();
3158     QVERIFY(object != 0);
3159
3160     QCOMPARE(object->property("test").toBool(), true);
3161
3162     delete object;
3163 }
3164
3165 // QTBUG-12457
3166 void tst_qdeclarativeecmascript::objectPassThroughSignals()
3167 {
3168     QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
3169
3170     QObject *object = component.create();
3171     QVERIFY(object != 0);
3172
3173     QCOMPARE(object->property("test").toBool(), true);
3174
3175     delete object;
3176 }
3177
3178 // QTBUG-20242
3179 void tst_qdeclarativeecmascript::booleanConversion()
3180 {
3181     QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
3182
3183     QObject *object = component.create();
3184     QVERIFY(object != 0);
3185
3186     QCOMPARE(object->property("test_true1").toBool(), true);
3187     QCOMPARE(object->property("test_true2").toBool(), true);
3188     QCOMPARE(object->property("test_true3").toBool(), true);
3189     QCOMPARE(object->property("test_true4").toBool(), true);
3190     QCOMPARE(object->property("test_true5").toBool(), true);
3191
3192     QCOMPARE(object->property("test_false1").toBool(), false);
3193     QCOMPARE(object->property("test_false2").toBool(), false);
3194     QCOMPARE(object->property("test_false3").toBool(), false);
3195
3196     delete object;
3197 }
3198
3199 // Test that assigning a null object works 
3200 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
3201 void tst_qdeclarativeecmascript::nullObjectBinding()
3202 {
3203     QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
3204
3205     QObject *object = component.create();
3206     QVERIFY(object != 0);
3207
3208     QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3209
3210     delete object;
3211 }
3212
3213 // Test that bindings don't evaluate once the engine has been destroyed
3214 void tst_qdeclarativeecmascript::deletedEngine()
3215 {
3216     QDeclarativeEngine *engine = new QDeclarativeEngine;
3217     QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3218
3219     QObject *object = component.create();
3220     QVERIFY(object != 0);
3221
3222     QCOMPARE(object->property("a").toInt(), 39);
3223     object->setProperty("b", QVariant(9));
3224     QCOMPARE(object->property("a").toInt(), 117);
3225
3226     delete engine;
3227
3228     QCOMPARE(object->property("a").toInt(), 117);
3229     object->setProperty("b", QVariant(10));
3230     QCOMPARE(object->property("a").toInt(), 117);
3231
3232     delete object;
3233 }
3234
3235 // Test the crashing part of QTBUG-9705
3236 void tst_qdeclarativeecmascript::libraryScriptAssert()
3237 {
3238     QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3239
3240     QObject *object = component.create();
3241     QVERIFY(object != 0);
3242
3243     delete object;
3244 }
3245
3246 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3247 {
3248     QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3249
3250     QObject *object = component.create();
3251     QVERIFY(object != 0);
3252
3253     QCOMPARE(object->property("test1").toInt(), 10);
3254     QCOMPARE(object->property("test2").toInt(), 11);
3255
3256     object->setProperty("runTest", true);
3257
3258     QCOMPARE(object->property("test1"), QVariant());
3259     QCOMPARE(object->property("test2"), QVariant());
3260
3261
3262     delete object;
3263 }
3264
3265 void tst_qdeclarativeecmascript::qtbug_9792()
3266 {
3267     QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3268
3269     QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3270
3271     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3272     QVERIFY(object != 0);
3273
3274     QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3275     object->basicSignal();
3276
3277     delete context;
3278
3279     transientErrorsMsgCount = 0;
3280     QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3281
3282     object->basicSignal();
3283     
3284     qInstallMsgHandler(old);
3285
3286     QCOMPARE(transientErrorsMsgCount, 0);
3287
3288     delete object;
3289 }
3290
3291 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3292 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3293 {
3294     QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3295
3296     QObject *o = component.create();
3297     QVERIFY(o != 0);
3298
3299     QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3300     QVERIFY(nested != 0);
3301
3302     QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3303
3304     delete nested;
3305     nested = qvariant_cast<QObject *>(o->property("object"));
3306     QVERIFY(nested == 0);
3307
3308     // If the bug is present, the next line will crash
3309     delete o;
3310 }
3311
3312 // Test that we shut down without stupid warnings
3313 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3314 {
3315     {
3316     QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3317
3318     QObject *o = component.create();
3319
3320     transientErrorsMsgCount = 0;
3321     QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3322
3323     delete o;
3324
3325     qInstallMsgHandler(old);
3326
3327     QCOMPARE(transientErrorsMsgCount, 0);
3328     }
3329
3330
3331     {
3332     QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3333
3334     QObject *o = component.create();
3335
3336     transientErrorsMsgCount = 0;
3337     QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3338
3339     delete o;
3340
3341     qInstallMsgHandler(old);
3342
3343     QCOMPARE(transientErrorsMsgCount, 0);
3344     }
3345 }
3346
3347 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3348 {
3349     {
3350     QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3351
3352     MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3353     QVERIFY(o != 0);
3354
3355     QVERIFY(o->objectProperty() != 0);
3356
3357     o->setProperty("runTest", true);
3358
3359     QVERIFY(o->objectProperty() == 0);
3360
3361     delete o;
3362     }
3363
3364     {
3365     QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3366
3367     MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3368     QVERIFY(o != 0);
3369
3370     QVERIFY(o->objectProperty() == 0);
3371
3372     delete o;
3373     }
3374 }
3375
3376 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3377 {
3378     QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3379
3380     QString url = component.url().toString();
3381     QString warning = url + ":4: Unable to assign a function to a property.";
3382     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3383     
3384     MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3385     QVERIFY(o != 0);
3386
3387     QVERIFY(!o->property("a").isValid());
3388
3389     delete o;
3390 }
3391
3392 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3393 {
3394     QFETCH(QString, triggerProperty);
3395
3396     QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3397     QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3398
3399     MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3400     QVERIFY(o != 0);
3401     QVERIFY(!o->property("a").isValid());
3402
3403     o->setProperty("aNumber", QVariant(5));
3404     o->setProperty(triggerProperty.toUtf8().constData(), true);
3405     QCOMPARE(o->property("a"), QVariant(50));
3406
3407     o->setProperty("aNumber", QVariant(10));
3408     QCOMPARE(o->property("a"), QVariant(100));
3409
3410     delete o;
3411 }
3412
3413 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3414 {
3415     QTest::addColumn<QString>("triggerProperty");
3416
3417     QTest::newRow("assign to property") << "assignToProperty";
3418     QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3419
3420     QTest::newRow("assign to value type") << "assignToValueType";
3421
3422     QTest::newRow("use 'this'") << "assignWithThis";
3423     QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3424 }
3425
3426 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3427 {
3428     QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3429     QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3430
3431     MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3432     QVERIFY(o != 0);
3433     QVERIFY(!o->property("a").isValid());
3434
3435     o->setProperty("assignFuncWithoutReturn", true);
3436     QVERIFY(!o->property("a").isValid());
3437
3438     QString url = component.url().toString();
3439     QString warning = url + ":67: Unable to assign QString to int";
3440     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3441     o->setProperty("assignWrongType", true);
3442
3443     warning = url + ":71: Unable to assign QString to int";
3444     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3445     o->setProperty("assignWrongTypeToValueType", true);
3446
3447     delete o;
3448 }
3449
3450 void tst_qdeclarativeecmascript::eval()
3451 {
3452     QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3453
3454     QObject *o = component.create();
3455     QVERIFY(o != 0);
3456
3457     QCOMPARE(o->property("test1").toBool(), true);
3458     QCOMPARE(o->property("test2").toBool(), true);
3459     QCOMPARE(o->property("test3").toBool(), true);
3460     QCOMPARE(o->property("test4").toBool(), true);
3461     QCOMPARE(o->property("test5").toBool(), true);
3462
3463     delete o;
3464 }
3465
3466 void tst_qdeclarativeecmascript::function()
3467 {
3468     QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3469
3470     QObject *o = component.create();
3471     QVERIFY(o != 0);
3472
3473     QCOMPARE(o->property("test1").toBool(), true);
3474     QCOMPARE(o->property("test2").toBool(), true);
3475     QCOMPARE(o->property("test3").toBool(), true);
3476
3477     delete o;
3478 }
3479
3480 // Test the "Qt.include" method
3481 void tst_qdeclarativeecmascript::include()
3482 {
3483     // Non-library relative include
3484     {
3485     QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3486     QObject *o = component.create();
3487     QVERIFY(o != 0);
3488
3489     QCOMPARE(o->property("test0").toInt(), 99);
3490     QCOMPARE(o->property("test1").toBool(), true);
3491     QCOMPARE(o->property("test2").toBool(), true);
3492     QCOMPARE(o->property("test2_1").toBool(), true);
3493     QCOMPARE(o->property("test3").toBool(), true);
3494     QCOMPARE(o->property("test3_1").toBool(), true);
3495
3496     delete o;
3497     }
3498
3499     // Library relative include
3500     {
3501     QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3502     QObject *o = component.create();
3503     QVERIFY(o != 0);
3504
3505     QCOMPARE(o->property("test0").toInt(), 99);
3506     QCOMPARE(o->property("test1").toBool(), true);
3507     QCOMPARE(o->property("test2").toBool(), true);
3508     QCOMPARE(o->property("test2_1").toBool(), true);
3509     QCOMPARE(o->property("test3").toBool(), true);
3510     QCOMPARE(o->property("test3_1").toBool(), true);
3511
3512     delete o;
3513     }
3514
3515     // Callback
3516     {
3517     QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3518     QObject *o = component.create();
3519     QVERIFY(o != 0);
3520
3521     QCOMPARE(o->property("test1").toBool(), true);
3522     QCOMPARE(o->property("test2").toBool(), true);
3523     QCOMPARE(o->property("test3").toBool(), true);
3524     QCOMPARE(o->property("test4").toBool(), true);
3525     QCOMPARE(o->property("test5").toBool(), true);
3526     QCOMPARE(o->property("test6").toBool(), true);
3527
3528     delete o;
3529     }
3530
3531     // Including file with ".pragma library"
3532     {
3533     QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3534     QObject *o = component.create();
3535     QVERIFY(o != 0);
3536     QCOMPARE(o->property("test1").toInt(), 100);
3537
3538     delete o;
3539     }
3540
3541     // Remote - success
3542     {
3543     TestHTTPServer server(8111);
3544     QVERIFY(server.isValid());
3545     server.serveDirectory(SRCDIR "/data");
3546
3547     QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3548     QObject *o = component.create();
3549     QVERIFY(o != 0);
3550
3551     QTRY_VERIFY(o->property("done").toBool() == true);
3552     QTRY_VERIFY(o->property("done2").toBool() == true);
3553
3554     QCOMPARE(o->property("test1").toBool(), true);
3555     QCOMPARE(o->property("test2").toBool(), true);
3556     QCOMPARE(o->property("test3").toBool(), true);
3557     QCOMPARE(o->property("test4").toBool(), true);
3558     QCOMPARE(o->property("test5").toBool(), true);
3559
3560     QCOMPARE(o->property("test6").toBool(), true);
3561     QCOMPARE(o->property("test7").toBool(), true);
3562     QCOMPARE(o->property("test8").toBool(), true);
3563     QCOMPARE(o->property("test9").toBool(), true);
3564     QCOMPARE(o->property("test10").toBool(), true);
3565
3566     delete o;
3567     }
3568
3569     // Remote - error
3570     {
3571     TestHTTPServer server(8111);
3572     QVERIFY(server.isValid());
3573     server.serveDirectory(SRCDIR "/data");
3574
3575     QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3576     QObject *o = component.create();
3577     QVERIFY(o != 0);
3578
3579     QTRY_VERIFY(o->property("done").toBool() == true);
3580
3581     QCOMPARE(o->property("test1").toBool(), true);
3582     QCOMPARE(o->property("test2").toBool(), true);
3583     QCOMPARE(o->property("test3").toBool(), true);
3584
3585     delete o;
3586     }
3587 }
3588
3589 void tst_qdeclarativeecmascript::qtbug_10696()
3590 {
3591     QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3592     QObject *o = component.create();
3593     QVERIFY(o != 0);
3594     delete o;
3595 }
3596
3597 void tst_qdeclarativeecmascript::qtbug_11606()
3598 {
3599     QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3600     QObject *o = component.create();
3601     QVERIFY(o != 0);
3602     QCOMPARE(o->property("test").toBool(), true);
3603     delete o;
3604 }
3605
3606 void tst_qdeclarativeecmascript::qtbug_11600()
3607 {
3608     QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3609     QObject *o = component.create();
3610     QVERIFY(o != 0);
3611     QCOMPARE(o->property("test").toBool(), true);
3612     delete o;
3613 }
3614
3615 // Reading and writing non-scriptable properties should fail
3616 void tst_qdeclarativeecmascript::nonscriptable()
3617 {
3618     QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3619     QObject *o = component.create();
3620     QVERIFY(o != 0);
3621     QCOMPARE(o->property("readOk").toBool(), true);
3622     QCOMPARE(o->property("writeOk").toBool(), true);
3623     delete o;
3624 }
3625
3626 // deleteLater() should not be callable from QML
3627 void tst_qdeclarativeecmascript::deleteLater()
3628 {
3629     QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3630     QObject *o = component.create();
3631     QVERIFY(o != 0);
3632     QCOMPARE(o->property("test").toBool(), true);
3633     delete o;
3634 }
3635
3636 void tst_qdeclarativeecmascript::in()
3637 {
3638     QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3639     QObject *o = component.create();
3640     QVERIFY(o != 0);
3641     QCOMPARE(o->property("test1").toBool(), true);
3642     QCOMPARE(o->property("test2").toBool(), true);
3643     delete o;
3644 }
3645
3646 void tst_qdeclarativeecmascript::sharedAttachedObject()
3647 {
3648     QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3649     QObject *o = component.create();
3650     QVERIFY(o != 0);
3651     QCOMPARE(o->property("test1").toBool(), true);
3652     QCOMPARE(o->property("test2").toBool(), true);
3653     delete o;
3654 }
3655
3656 // QTBUG-13999
3657 void tst_qdeclarativeecmascript::objectName()
3658 {
3659     QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3660     QObject *o = component.create();
3661     QVERIFY(o != 0);
3662
3663     QCOMPARE(o->property("test1").toString(), QString("hello"));
3664     QCOMPARE(o->property("test2").toString(), QString("ell"));
3665
3666     o->setObjectName("world");
3667
3668     QCOMPARE(o->property("test1").toString(), QString("world"));
3669     QCOMPARE(o->property("test2").toString(), QString("orl"));
3670
3671     delete o;
3672 }
3673
3674 void tst_qdeclarativeecmascript::writeRemovesBinding()
3675 {
3676     QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3677     QObject *o = component.create();
3678     QVERIFY(o != 0);
3679
3680     QCOMPARE(o->property("test").toBool(), true);
3681
3682     delete o;
3683 }
3684
3685 // Test bindings assigned to alias properties actually assign to the alias' target
3686 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3687 {
3688     QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3689     QObject *o = component.create();
3690     QVERIFY(o != 0);
3691
3692     QCOMPARE(o->property("test").toBool(), true);
3693
3694     delete o;
3695 }
3696
3697 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3698 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3699 {
3700     { 
3701     QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3702     QObject *o = component.create();
3703     QVERIFY(o != 0);
3704
3705     QCOMPARE(o->property("test").toBool(), true);
3706
3707     delete o;
3708     }
3709
3710     {
3711     QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3712     QObject *o = component.create();
3713     QVERIFY(o != 0);
3714
3715     QCOMPARE(o->property("test").toBool(), true);
3716
3717     delete o;
3718     }
3719
3720     {
3721     QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3722     QObject *o = component.create();
3723     QVERIFY(o != 0);
3724
3725     QCOMPARE(o->property("test").toBool(), true);
3726
3727     delete o;
3728     }
3729 }
3730
3731 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3732 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3733 {
3734     {
3735     QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3736     QObject *o = component.create();
3737     QVERIFY(o != 0);
3738
3739     QCOMPARE(o->property("test").toBool(), true);
3740
3741     delete o;
3742     }
3743
3744     {
3745     QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3746     QObject *o = component.create();
3747     QVERIFY(o != 0);
3748
3749     QCOMPARE(o->property("test").toBool(), true);
3750
3751     delete o;
3752     }
3753
3754     {
3755     QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3756     QObject *o = component.create();
3757     QVERIFY(o != 0);
3758
3759     QCOMPARE(o->property("test").toBool(), true);
3760
3761     delete o;
3762     }
3763 }
3764
3765 // Allow an alais to a composite element
3766 // QTBUG-20200
3767 void tst_qdeclarativeecmascript::aliasToCompositeElement()
3768 {
3769     QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
3770
3771     QObject *object = component.create();
3772     QVERIFY(object != 0);
3773
3774     delete object;
3775 }
3776
3777 void tst_qdeclarativeecmascript::revisionErrors()
3778 {
3779     {
3780         QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3781         QString url = component.url().toString();
3782
3783         QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3784         QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3785         QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3786
3787         QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3788         QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3789         QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3790         MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3791         QVERIFY(object != 0);
3792         delete object;
3793     }
3794     {
3795         QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3796         QString url = component.url().toString();
3797
3798         // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3799         // method2, prop2 from MyRevisionedClass not available
3800         // method4, prop4 from MyRevisionedSubclass not available
3801         QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3802         QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3803         QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3804         QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3805         QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3806
3807         QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3808         QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3809         QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3810         QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3811         QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3812         MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3813         QVERIFY(object != 0);
3814         delete object;
3815     }
3816     {
3817         QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3818         QString url = component.url().toString();
3819
3820         // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3821         // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3822         QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3823         QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3824         QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3825         QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3826         QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3827         QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3828         MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3829         QVERIFY(object != 0);
3830         delete object;
3831     }
3832 }
3833
3834 void tst_qdeclarativeecmascript::revision()
3835 {
3836     {
3837         QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3838         QString url = component.url().toString();
3839
3840         MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3841         QVERIFY(object != 0);
3842         delete object;
3843     }
3844     {
3845         QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3846         QString url = component.url().toString();
3847
3848         MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3849         QVERIFY(object != 0);
3850         delete object;
3851     }
3852     {
3853         QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3854         QString url = component.url().toString();
3855
3856         MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3857         QVERIFY(object != 0);
3858         delete object;
3859     }
3860     // Test that non-root classes can resolve revisioned methods
3861     {
3862         QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3863
3864         QObject *object = component.create();
3865         QVERIFY(object != 0);
3866         QCOMPARE(object->property("test").toReal(), 11.);
3867         delete object;
3868     }
3869 }
3870
3871 void tst_qdeclarativeecmascript::realToInt()
3872 {
3873     QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3874     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3875     QVERIFY(object != 0);
3876
3877     QMetaObject::invokeMethod(object, "test1");
3878     QCOMPARE(object->value(), int(4));
3879     QMetaObject::invokeMethod(object, "test2");
3880     QCOMPARE(object->value(), int(8));
3881 }
3882 void tst_qdeclarativeecmascript::dynamicString()
3883 {
3884     QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
3885     QObject *object = component.create();
3886     QVERIFY(object != 0);
3887     QCOMPARE(object->property("stringProperty").toString(),
3888              QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
3889 }
3890
3891 QTEST_MAIN(tst_qdeclarativeecmascript)
3892
3893 #include "tst_qdeclarativeecmascript.moc"