1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativecomponent.h>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativeexpression.h>
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtCore/qfileinfo.h>
47 #include <QtCore/qdebug.h>
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
49 #include <QtCore/qdir.h>
50 #include <QtCore/qnumeric.h>
51 #include <private/qdeclarativeengine_p.h>
52 #include "testtypes.h"
53 #include "testhttpserver.h"
54 #include "../../../shared/util.h"
57 // In Symbian OS test data is located in applications private dir
62 This test covers evaluation of ECMAScript expressions and bindings from within
63 QML. This does not include static QML language issues.
65 Static QML language issues are covered in qmllanguage
67 inline QUrl TEST_FILE(const QString &filename)
69 QFileInfo fileInfo(__FILE__);
70 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
73 inline QUrl TEST_FILE(const char *filename)
75 return TEST_FILE(QLatin1String(filename));
78 class tst_qdeclarativeecmascript : public QObject
82 tst_qdeclarativeecmascript() {}
86 void assignBasicTypes();
87 void idShortcutInvalidates();
88 void boolPropertiesEvaluateAsBool();
90 void signalAssignment();
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();
103 void valueTypeFunctions();
104 void constantsOverrideBindings();
105 void outerBindingOverridesInnerBinding();
106 void aliasPropertyAndBinding();
107 void aliasPropertyReset();
108 void nonExistentAttachedObject();
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();
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();
132 void undefinedResetsProperty();
133 void listToVariant();
134 void listAssignment();
135 void multiEngineObject();
136 void deletedObject();
137 void attachedPropertyScope();
138 void scriptConnect();
139 void scriptDisconnect();
141 void cppOwnershipReturnValue();
142 void ownershipCustomReturnValue();
143 void qlistqobjectMethods();
144 void strictlyEquals();
146 void numberAssignment();
147 void propertySplicing();
148 void signalWithUnknownTypes();
149 void signalWithJSValueInVariant_data();
150 void signalWithJSValueInVariant();
151 void signalWithJSValueInVariant_twoEngines_data();
152 void signalWithJSValueInVariant_twoEngines();
153 void moduleApi_data();
155 void importScripts();
156 void scarceResources();
157 void propertyChangeSlots();
158 void elementAssign();
159 void objectPassThroughSignals();
160 void booleanConversion();
161 void handleReferenceManagement();
165 void dynamicCreationCrash();
167 void nullObjectBinding();
168 void deletedEngine();
169 void libraryScriptAssert();
170 void variantsAssignedUndefined();
172 void qtcreatorbug_1289();
173 void noSpuriousWarningsAtShutdown();
174 void canAssignNullToQObject();
175 void functionAssignment_fromBinding();
176 void functionAssignment_fromJS();
177 void functionAssignment_fromJS_data();
178 void functionAssignmentfromJS_invalid();
184 void nonscriptable();
187 void sharedAttachedObject();
189 void writeRemovesBinding();
190 void aliasBindingsAssignCorrectly();
191 void aliasBindingsOverrideTarget();
192 void aliasWritesOverrideBindings();
193 void aliasToCompositeElement();
195 void dynamicString();
197 void signalHandlers();
199 void callQtInvokables();
200 void invokableObjectArg();
201 void invokableObjectRet();
203 void revisionErrors();
206 void automaticSemicolon();
209 QDeclarativeEngine engine;
212 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
214 void tst_qdeclarativeecmascript::assignBasicTypes()
217 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
218 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
219 QVERIFY(object != 0);
220 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
221 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
222 QCOMPARE(object->stringProperty(), QString("Hello World!"));
223 QCOMPARE(object->uintProperty(), uint(10));
224 QCOMPARE(object->intProperty(), -19);
225 QCOMPARE((float)object->realProperty(), float(23.2));
226 QCOMPARE((float)object->doubleProperty(), float(-19.75));
227 QCOMPARE((float)object->floatProperty(), float(8.5));
228 QCOMPARE(object->colorProperty(), QColor("red"));
229 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
230 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
231 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
232 QCOMPARE(object->pointProperty(), QPoint(99,13));
233 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
234 QCOMPARE(object->sizeProperty(), QSize(99, 13));
235 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
236 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
237 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
238 QCOMPARE(object->boolProperty(), true);
239 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
240 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
241 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
245 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
246 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
247 QVERIFY(object != 0);
248 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
249 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
250 QCOMPARE(object->stringProperty(), QString("Hello World!"));
251 QCOMPARE(object->uintProperty(), uint(10));
252 QCOMPARE(object->intProperty(), -19);
253 QCOMPARE((float)object->realProperty(), float(23.2));
254 QCOMPARE((float)object->doubleProperty(), float(-19.75));
255 QCOMPARE((float)object->floatProperty(), float(8.5));
256 QCOMPARE(object->colorProperty(), QColor("red"));
257 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
258 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
259 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
260 QCOMPARE(object->pointProperty(), QPoint(99,13));
261 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
262 QCOMPARE(object->sizeProperty(), QSize(99, 13));
263 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
264 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
265 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
266 QCOMPARE(object->boolProperty(), true);
267 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
268 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
269 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
274 void tst_qdeclarativeecmascript::idShortcutInvalidates()
277 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
278 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
279 QVERIFY(object != 0);
280 QVERIFY(object->objectProperty() != 0);
281 delete object->objectProperty();
282 QVERIFY(object->objectProperty() == 0);
287 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
288 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
289 QVERIFY(object != 0);
290 QVERIFY(object->objectProperty() != 0);
291 delete object->objectProperty();
292 QVERIFY(object->objectProperty() == 0);
297 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
300 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
301 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
302 QVERIFY(object != 0);
303 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
307 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
308 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
309 QVERIFY(object != 0);
310 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
315 void tst_qdeclarativeecmascript::signalAssignment()
318 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
319 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
320 QVERIFY(object != 0);
321 QCOMPARE(object->string(), QString());
322 emit object->basicSignal();
323 QCOMPARE(object->string(), QString("pass"));
328 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
329 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
330 QVERIFY(object != 0);
331 QCOMPARE(object->string(), QString());
332 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
333 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
338 void tst_qdeclarativeecmascript::methods()
341 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
342 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
343 QVERIFY(object != 0);
344 QCOMPARE(object->methodCalled(), false);
345 QCOMPARE(object->methodIntCalled(), false);
346 emit object->basicSignal();
347 QCOMPARE(object->methodCalled(), true);
348 QCOMPARE(object->methodIntCalled(), false);
353 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
354 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
355 QVERIFY(object != 0);
356 QCOMPARE(object->methodCalled(), false);
357 QCOMPARE(object->methodIntCalled(), false);
358 emit object->basicSignal();
359 QCOMPARE(object->methodCalled(), false);
360 QCOMPARE(object->methodIntCalled(), true);
365 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
366 QObject *object = component.create();
367 QVERIFY(object != 0);
368 QCOMPARE(object->property("test").toInt(), 19);
373 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
374 QObject *object = component.create();
375 QVERIFY(object != 0);
376 QCOMPARE(object->property("test").toInt(), 19);
377 QCOMPARE(object->property("test2").toInt(), 17);
378 QCOMPARE(object->property("test3").toInt(), 16);
383 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
384 QObject *object = component.create();
385 QVERIFY(object != 0);
386 QCOMPARE(object->property("test").toInt(), 9);
391 void tst_qdeclarativeecmascript::bindingLoop()
393 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
394 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
395 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
396 QObject *object = component.create();
397 QVERIFY(object != 0);
401 void tst_qdeclarativeecmascript::basicExpressions_data()
403 QTest::addColumn<QString>("expression");
404 QTest::addColumn<QVariant>("result");
405 QTest::addColumn<bool>("nest");
407 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
408 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
409 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
410 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
411 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
412 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
413 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
414 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
415 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
416 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
417 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
418 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
419 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
420 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
421 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
422 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
423 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
424 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
425 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
428 void tst_qdeclarativeecmascript::basicExpressions()
430 QFETCH(QString, expression);
431 QFETCH(QVariant, result);
437 MyDefaultObject1 default1;
438 MyDefaultObject3 default3;
439 object1.setStringProperty("Object1");
440 object2.setStringProperty("Object2");
441 object3.setStringProperty("Object3");
443 QDeclarativeContext context(engine.rootContext());
444 QDeclarativeContext nestedContext(&context);
446 context.setContextObject(&default1);
447 context.setContextProperty("a", QVariant(1944));
448 context.setContextProperty("b", QVariant("Milk"));
449 context.setContextProperty("object", &object1);
450 context.setContextProperty("objectOverride", &object2);
451 nestedContext.setContextObject(&default3);
452 nestedContext.setContextProperty("b", QVariant("Cow"));
453 nestedContext.setContextProperty("objectOverride", &object3);
454 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
456 MyExpression expr(nest?&nestedContext:&context, expression);
457 QCOMPARE(expr.evaluate(), result);
460 void tst_qdeclarativeecmascript::arrayExpressions()
466 QDeclarativeContext context(engine.rootContext());
467 context.setContextProperty("a", &obj1);
468 context.setContextProperty("b", &obj2);
469 context.setContextProperty("c", &obj3);
471 MyExpression expr(&context, "[a, b, c, 10]");
472 QVariant result = expr.evaluate();
473 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
474 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
475 QCOMPARE(list.count(), 4);
476 QCOMPARE(list.at(0), &obj1);
477 QCOMPARE(list.at(1), &obj2);
478 QCOMPARE(list.at(2), &obj3);
479 QCOMPARE(list.at(3), (QObject *)0);
482 // Tests that modifying a context property will reevaluate expressions
483 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
485 QDeclarativeContext context(engine.rootContext());
488 MyQmlObject *object3 = new MyQmlObject;
490 object1.setStringProperty("Hello");
491 object2.setStringProperty("World");
493 context.setContextProperty("testProp", QVariant(1));
494 context.setContextProperty("testObj", &object1);
495 context.setContextProperty("testObj2", object3);
498 MyExpression expr(&context, "testProp + 1");
499 QCOMPARE(expr.changed, false);
500 QCOMPARE(expr.evaluate(), QVariant(2));
502 context.setContextProperty("testProp", QVariant(2));
503 QCOMPARE(expr.changed, true);
504 QCOMPARE(expr.evaluate(), QVariant(3));
508 MyExpression expr(&context, "testProp + testProp + testProp");
509 QCOMPARE(expr.changed, false);
510 QCOMPARE(expr.evaluate(), QVariant(6));
512 context.setContextProperty("testProp", QVariant(4));
513 QCOMPARE(expr.changed, true);
514 QCOMPARE(expr.evaluate(), QVariant(12));
518 MyExpression expr(&context, "testObj.stringProperty");
519 QCOMPARE(expr.changed, false);
520 QCOMPARE(expr.evaluate(), QVariant("Hello"));
522 context.setContextProperty("testObj", &object2);
523 QCOMPARE(expr.changed, true);
524 QCOMPARE(expr.evaluate(), QVariant("World"));
528 MyExpression expr(&context, "testObj.stringProperty /**/");
529 QCOMPARE(expr.changed, false);
530 QCOMPARE(expr.evaluate(), QVariant("World"));
532 context.setContextProperty("testObj", &object1);
533 QCOMPARE(expr.changed, true);
534 QCOMPARE(expr.evaluate(), QVariant("Hello"));
538 MyExpression expr(&context, "testObj2");
539 QCOMPARE(expr.changed, false);
540 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
546 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
548 QDeclarativeContext context(engine.rootContext());
552 context.setContextProperty("testObj", &object1);
554 object1.setStringProperty(QLatin1String("Hello"));
555 object2.setStringProperty(QLatin1String("Dog"));
556 object3.setStringProperty(QLatin1String("Cat"));
559 MyExpression expr(&context, "testObj.stringProperty");
560 QCOMPARE(expr.changed, false);
561 QCOMPARE(expr.evaluate(), QVariant("Hello"));
563 object1.setStringProperty(QLatin1String("World"));
564 QCOMPARE(expr.changed, true);
565 QCOMPARE(expr.evaluate(), QVariant("World"));
569 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
570 QCOMPARE(expr.changed, false);
571 QCOMPARE(expr.evaluate(), QVariant());
573 object1.setObjectProperty(&object2);
574 QCOMPARE(expr.changed, true);
575 expr.changed = false;
576 QCOMPARE(expr.evaluate(), QVariant("Dog"));
578 object1.setObjectProperty(&object3);
579 QCOMPARE(expr.changed, true);
580 expr.changed = false;
581 QCOMPARE(expr.evaluate(), QVariant("Cat"));
583 object1.setObjectProperty(0);
584 QCOMPARE(expr.changed, true);
585 expr.changed = false;
586 QCOMPARE(expr.evaluate(), QVariant());
588 object1.setObjectProperty(&object3);
589 QCOMPARE(expr.changed, true);
590 expr.changed = false;
591 QCOMPARE(expr.evaluate(), QVariant("Cat"));
593 object3.setStringProperty("Donkey");
594 QCOMPARE(expr.changed, true);
595 expr.changed = false;
596 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
600 void tst_qdeclarativeecmascript::deferredProperties()
602 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
603 MyDeferredObject *object =
604 qobject_cast<MyDeferredObject *>(component.create());
605 QVERIFY(object != 0);
606 QCOMPARE(object->value(), 0);
607 QVERIFY(object->objectProperty() == 0);
608 QVERIFY(object->objectProperty2() != 0);
609 qmlExecuteDeferred(object);
610 QCOMPARE(object->value(), 10);
611 QVERIFY(object->objectProperty() != 0);
612 MyQmlObject *qmlObject =
613 qobject_cast<MyQmlObject *>(object->objectProperty());
614 QVERIFY(qmlObject != 0);
615 QCOMPARE(qmlObject->value(), 10);
616 object->setValue(19);
617 QCOMPARE(qmlObject->value(), 19);
622 // Check errors on deferred properties are correctly emitted
623 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
625 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
626 MyDeferredObject *object =
627 qobject_cast<MyDeferredObject *>(component.create());
628 QVERIFY(object != 0);
629 QCOMPARE(object->value(), 0);
630 QVERIFY(object->objectProperty() == 0);
631 QVERIFY(object->objectProperty2() == 0);
633 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
634 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
636 qmlExecuteDeferred(object);
641 void tst_qdeclarativeecmascript::extensionObjects()
643 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
644 MyExtendedObject *object =
645 qobject_cast<MyExtendedObject *>(component.create());
646 QVERIFY(object != 0);
647 QCOMPARE(object->baseProperty(), 13);
648 QCOMPARE(object->coreProperty(), 9);
649 object->setProperty("extendedProperty", QVariant(11));
650 object->setProperty("baseExtendedProperty", QVariant(92));
651 QCOMPARE(object->coreProperty(), 11);
652 QCOMPARE(object->baseProperty(), 92);
654 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
656 QCOMPARE(nested->baseProperty(), 13);
657 QCOMPARE(nested->coreProperty(), 9);
658 nested->setProperty("extendedProperty", QVariant(11));
659 nested->setProperty("baseExtendedProperty", QVariant(92));
660 QCOMPARE(nested->coreProperty(), 11);
661 QCOMPARE(nested->baseProperty(), 92);
666 void tst_qdeclarativeecmascript::overrideExtensionProperties()
668 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
669 OverrideDefaultPropertyObject *object =
670 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
671 QVERIFY(object != 0);
672 QVERIFY(object->secondProperty() != 0);
673 QVERIFY(object->firstProperty() == 0);
678 void tst_qdeclarativeecmascript::attachedProperties()
681 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
682 QObject *object = component.create();
683 QVERIFY(object != 0);
684 QCOMPARE(object->property("a").toInt(), 19);
685 QCOMPARE(object->property("b").toInt(), 19);
686 QCOMPARE(object->property("c").toInt(), 19);
687 QCOMPARE(object->property("d").toInt(), 19);
692 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
693 QObject *object = component.create();
694 QVERIFY(object != 0);
695 QCOMPARE(object->property("a").toInt(), 26);
696 QCOMPARE(object->property("b").toInt(), 26);
697 QCOMPARE(object->property("c").toInt(), 26);
698 QCOMPARE(object->property("d").toInt(), 26);
704 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
705 QObject *object = component.create();
706 QVERIFY(object != 0);
708 QMetaObject::invokeMethod(object, "writeValue2");
710 MyQmlAttachedObject *attached =
711 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
712 QVERIFY(attached != 0);
714 QCOMPARE(attached->value2(), 9);
719 void tst_qdeclarativeecmascript::enums()
723 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
724 QObject *object = component.create();
725 QVERIFY(object != 0);
727 QCOMPARE(object->property("a").toInt(), 0);
728 QCOMPARE(object->property("b").toInt(), 1);
729 QCOMPARE(object->property("c").toInt(), 2);
730 QCOMPARE(object->property("d").toInt(), 3);
731 QCOMPARE(object->property("e").toInt(), 0);
732 QCOMPARE(object->property("f").toInt(), 1);
733 QCOMPARE(object->property("g").toInt(), 2);
734 QCOMPARE(object->property("h").toInt(), 3);
735 QCOMPARE(object->property("i").toInt(), 19);
736 QCOMPARE(object->property("j").toInt(), 19);
740 // Non-existent enums
742 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
744 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
745 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
746 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
747 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
749 QObject *object = component.create();
750 QVERIFY(object != 0);
751 QCOMPARE(object->property("a").toInt(), 0);
752 QCOMPARE(object->property("b").toInt(), 0);
758 void tst_qdeclarativeecmascript::valueTypeFunctions()
760 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
761 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
763 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
764 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
770 Tests that writing a constant to a property with a binding on it disables the
773 void tst_qdeclarativeecmascript::constantsOverrideBindings()
777 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
778 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
779 QVERIFY(object != 0);
781 QCOMPARE(object->property("c2").toInt(), 0);
782 object->setProperty("c1", QVariant(9));
783 QCOMPARE(object->property("c2").toInt(), 9);
785 emit object->basicSignal();
787 QCOMPARE(object->property("c2").toInt(), 13);
788 object->setProperty("c1", QVariant(8));
789 QCOMPARE(object->property("c2").toInt(), 13);
794 // During construction
796 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
797 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
798 QVERIFY(object != 0);
800 QCOMPARE(object->property("c1").toInt(), 0);
801 QCOMPARE(object->property("c2").toInt(), 10);
802 object->setProperty("c1", QVariant(9));
803 QCOMPARE(object->property("c1").toInt(), 9);
804 QCOMPARE(object->property("c2").toInt(), 10);
812 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
813 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
814 QVERIFY(object != 0);
816 QCOMPARE(object->property("c2").toInt(), 0);
817 object->setProperty("c1", QVariant(9));
818 QCOMPARE(object->property("c2").toInt(), 9);
820 object->setProperty("c2", QVariant(13));
821 QCOMPARE(object->property("c2").toInt(), 13);
822 object->setProperty("c1", QVariant(7));
823 QCOMPARE(object->property("c1").toInt(), 7);
824 QCOMPARE(object->property("c2").toInt(), 13);
832 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
833 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
834 QVERIFY(object != 0);
836 QCOMPARE(object->property("c1").toInt(), 0);
837 QCOMPARE(object->property("c3").toInt(), 10);
838 object->setProperty("c1", QVariant(9));
839 QCOMPARE(object->property("c1").toInt(), 9);
840 QCOMPARE(object->property("c3").toInt(), 10);
847 Tests that assigning a binding to a property that already has a binding causes
848 the original binding to be disabled.
850 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
852 QDeclarativeComponent component(&engine,
853 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
854 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
855 QVERIFY(object != 0);
857 QCOMPARE(object->property("c1").toInt(), 0);
858 QCOMPARE(object->property("c2").toInt(), 0);
859 QCOMPARE(object->property("c3").toInt(), 0);
861 object->setProperty("c1", QVariant(9));
862 QCOMPARE(object->property("c1").toInt(), 9);
863 QCOMPARE(object->property("c2").toInt(), 0);
864 QCOMPARE(object->property("c3").toInt(), 0);
866 object->setProperty("c3", QVariant(8));
867 QCOMPARE(object->property("c1").toInt(), 9);
868 QCOMPARE(object->property("c2").toInt(), 8);
869 QCOMPARE(object->property("c3").toInt(), 8);
875 Access a non-existent attached object.
877 Tests for a regression where this used to crash.
879 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
881 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
883 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
884 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
886 QObject *object = component.create();
887 QVERIFY(object != 0);
892 void tst_qdeclarativeecmascript::scope()
895 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
896 QObject *object = component.create();
897 QVERIFY(object != 0);
899 QCOMPARE(object->property("test1").toInt(), 1);
900 QCOMPARE(object->property("test2").toInt(), 2);
901 QCOMPARE(object->property("test3").toString(), QString("1Test"));
902 QCOMPARE(object->property("test4").toString(), QString("2Test"));
903 QCOMPARE(object->property("test5").toInt(), 1);
904 QCOMPARE(object->property("test6").toInt(), 1);
905 QCOMPARE(object->property("test7").toInt(), 2);
906 QCOMPARE(object->property("test8").toInt(), 2);
907 QCOMPARE(object->property("test9").toInt(), 1);
908 QCOMPARE(object->property("test10").toInt(), 3);
914 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
915 QObject *object = component.create();
916 QVERIFY(object != 0);
918 QCOMPARE(object->property("test1").toInt(), 19);
919 QCOMPARE(object->property("test2").toInt(), 19);
920 QCOMPARE(object->property("test3").toInt(), 14);
921 QCOMPARE(object->property("test4").toInt(), 14);
922 QCOMPARE(object->property("test5").toInt(), 24);
923 QCOMPARE(object->property("test6").toInt(), 24);
929 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
930 QObject *object = component.create();
931 QVERIFY(object != 0);
933 QCOMPARE(object->property("test1").toBool(), true);
934 QCOMPARE(object->property("test2").toBool(), true);
935 QCOMPARE(object->property("test3").toBool(), true);
940 // Signal argument scope
942 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
943 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
944 QVERIFY(object != 0);
946 QCOMPARE(object->property("test").toInt(), 0);
947 QCOMPARE(object->property("test2").toString(), QString());
949 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
951 QCOMPARE(object->property("test").toInt(), 13);
952 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
958 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
959 QObject *object = component.create();
960 QVERIFY(object != 0);
962 QCOMPARE(object->property("test1").toBool(), true);
963 QCOMPARE(object->property("test2").toBool(), true);
969 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
970 QObject *object = component.create();
971 QVERIFY(object != 0);
973 QCOMPARE(object->property("test").toBool(), true);
979 // In 4.7, non-library javascript files that had no imports shared the imports of their
981 void tst_qdeclarativeecmascript::importScope()
983 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
984 QObject *o = component.create();
987 QCOMPARE(o->property("test").toInt(), 240);
993 Tests that "any" type passes through a synthesized signal parameter. This
994 is essentially a test of QDeclarativeMetaType::copy()
996 void tst_qdeclarativeecmascript::signalParameterTypes()
998 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
999 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1000 QVERIFY(object != 0);
1002 emit object->basicSignal();
1004 QCOMPARE(object->property("intProperty").toInt(), 10);
1005 QCOMPARE(object->property("realProperty").toReal(), 19.2);
1006 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
1007 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
1008 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
1009 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
1015 Test that two JS objects for the same QObject compare as equal.
1017 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1019 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1020 QObject *object = component.create();
1021 QVERIFY(object != 0);
1023 QCOMPARE(object->property("test1").toBool(), true);
1024 QCOMPARE(object->property("test2").toBool(), true);
1025 QCOMPARE(object->property("test3").toBool(), true);
1026 QCOMPARE(object->property("test4").toBool(), true);
1027 QCOMPARE(object->property("test5").toBool(), true);
1033 Confirm bindings and alias properties can coexist.
1035 Tests for a regression where the binding would not reevaluate.
1037 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1039 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1040 QObject *object = component.create();
1041 QVERIFY(object != 0);
1043 QCOMPARE(object->property("c2").toInt(), 3);
1044 QCOMPARE(object->property("c3").toInt(), 3);
1046 object->setProperty("c2", QVariant(19));
1048 QCOMPARE(object->property("c2").toInt(), 19);
1049 QCOMPARE(object->property("c3").toInt(), 19);
1055 Ensure that we can write undefined value to an alias property,
1056 and that the aliased property is reset correctly if possible.
1058 void tst_qdeclarativeecmascript::aliasPropertyReset()
1060 QObject *object = 0;
1062 // test that a manual write (of undefined) to a resettable aliased property succeeds
1063 QDeclarativeComponent c1(&engine, TEST_FILE("aliasreset/aliasPropertyReset.1.qml"));
1064 object = c1.create();
1065 QVERIFY(object != 0);
1066 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1067 QCOMPARE(object->property("aliasIsUndefined"), QVariant(false));
1068 QMetaObject::invokeMethod(object, "resetAliased");
1069 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1070 QCOMPARE(object->property("aliasIsUndefined"), QVariant(true));
1073 // test that a manual write (of undefined) to a resettable alias property succeeds
1074 QDeclarativeComponent c2(&engine, TEST_FILE("aliasreset/aliasPropertyReset.2.qml"));
1075 object = c2.create();
1076 QVERIFY(object != 0);
1077 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1078 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(false));
1079 QMetaObject::invokeMethod(object, "resetAlias");
1080 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1081 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(true));
1084 // test that an alias to a bound property works correctly
1085 QDeclarativeComponent c3(&engine, TEST_FILE("aliasreset/aliasPropertyReset.3.qml"));
1086 object = c3.create();
1087 QVERIFY(object != 0);
1088 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1089 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(false));
1090 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1091 QMetaObject::invokeMethod(object, "resetAlias");
1092 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1093 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(true));
1094 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1097 // test that a manual write (of undefined) to a resettable alias property
1098 // whose aliased property's object has been deleted, does not crash.
1099 QDeclarativeComponent c4(&engine, TEST_FILE("aliasreset/aliasPropertyReset.4.qml"));
1100 object = c4.create();
1101 QVERIFY(object != 0);
1102 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1103 QObject *loader = object->findChild<QObject*>("loader");
1104 QVERIFY(loader != 0);
1106 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // deletion should have caused value unset.
1107 QMetaObject::invokeMethod(object, "resetAlias"); // shouldn't crash.
1108 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1109 QMetaObject::invokeMethod(object, "setAlias"); // shouldn't crash, and shouldn't change value (since it's no longer referencing anything).
1110 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1113 // test that binding an alias property to an undefined value works correctly
1114 QDeclarativeComponent c5(&engine, TEST_FILE("aliasreset/aliasPropertyReset.5.qml"));
1115 object = c5.create();
1116 QVERIFY(object != 0);
1117 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // bound to undefined value.
1120 // test that a manual write (of undefined) to a non-resettable property fails properly
1121 QUrl url = TEST_FILE("aliasreset/aliasPropertyReset.error.1.qml");
1122 QString warning1 = url.toString() + QLatin1String(":15: Error: Cannot assign [undefined] to int");
1123 QDeclarativeComponent e1(&engine, url);
1124 object = e1.create();
1125 QVERIFY(object != 0);
1126 QCOMPARE(object->property("intAlias").value<int>(), 12);
1127 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1128 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1129 QMetaObject::invokeMethod(object, "resetAlias");
1130 QCOMPARE(object->property("intAlias").value<int>(), 12);
1131 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1135 void tst_qdeclarativeecmascript::dynamicCreation_data()
1137 QTest::addColumn<QString>("method");
1138 QTest::addColumn<QString>("createdName");
1140 QTest::newRow("One") << "createOne" << "objectOne";
1141 QTest::newRow("Two") << "createTwo" << "objectTwo";
1142 QTest::newRow("Three") << "createThree" << "objectThree";
1146 Test using createQmlObject to dynamically generate an item
1147 Also using createComponent is tested.
1149 void tst_qdeclarativeecmascript::dynamicCreation()
1151 QFETCH(QString, method);
1152 QFETCH(QString, createdName);
1154 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1155 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1156 QVERIFY(object != 0);
1158 QMetaObject::invokeMethod(object, method.toUtf8());
1159 QObject *created = object->objectProperty();
1161 QCOMPARE(created->objectName(), createdName);
1167 Tests the destroy function
1169 void tst_qdeclarativeecmascript::dynamicDestruction()
1172 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1173 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1174 QVERIFY(object != 0);
1175 QDeclarativeGuard<QObject> createdQmlObject = 0;
1177 QMetaObject::invokeMethod(object, "create");
1178 createdQmlObject = object->objectProperty();
1179 QVERIFY(createdQmlObject);
1180 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1182 QMetaObject::invokeMethod(object, "killOther");
1183 QVERIFY(createdQmlObject);
1184 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1185 QVERIFY(createdQmlObject);
1186 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1187 if (createdQmlObject) {
1189 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1192 QVERIFY(!createdQmlObject);
1194 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1195 QMetaObject::invokeMethod(object, "killMe");
1198 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1203 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.2.qml"));
1204 QObject *o = component.create();
1207 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1209 QMetaObject::invokeMethod(o, "create");
1211 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
1213 QMetaObject::invokeMethod(o, "destroy");
1215 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1217 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1224 tests that id.toString() works
1226 void tst_qdeclarativeecmascript::objectToString()
1228 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1229 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1230 QVERIFY(object != 0);
1231 QMetaObject::invokeMethod(object, "testToString");
1232 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1233 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1239 tests that id.hasOwnProperty() works
1241 void tst_qdeclarativeecmascript::objectHasOwnProperty()
1243 QUrl url = TEST_FILE("declarativeHasOwnProperty.qml");
1244 QString warning1 = url.toString() + ":59: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1245 QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1246 QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1248 QDeclarativeComponent component(&engine, url);
1249 QObject *object = component.create();
1250 QVERIFY(object != 0);
1252 // test QObjects in QML
1253 QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
1254 QVERIFY(object->property("result").value<bool>() == true);
1255 QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
1256 QVERIFY(object->property("result").value<bool>() == false);
1258 // now test other types in QML
1259 QObject *child = object->findChild<QObject*>("typeObj");
1260 QVERIFY(child != 0);
1261 QMetaObject::invokeMethod(child, "testHasOwnPropertySuccess");
1262 QCOMPARE(child->property("valueTypeHasOwnProperty").toBool(), true);
1263 QCOMPARE(child->property("valueTypeHasOwnProperty2").toBool(), true);
1264 QCOMPARE(child->property("variantTypeHasOwnProperty").toBool(), true);
1265 QCOMPARE(child->property("stringTypeHasOwnProperty").toBool(), true);
1266 QCOMPARE(child->property("listTypeHasOwnProperty").toBool(), true);
1267 QCOMPARE(child->property("emptyListTypeHasOwnProperty").toBool(), true);
1268 QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
1269 QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
1270 QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
1271 QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
1272 QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
1274 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1275 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
1276 QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
1277 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1278 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
1279 QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
1280 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1281 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
1282 QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
1288 Tests bindings that indirectly cause their own deletion work.
1290 This test is best run under valgrind to ensure no invalid memory access occur.
1292 void tst_qdeclarativeecmascript::selfDeletingBinding()
1295 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1296 QObject *object = component.create();
1297 QVERIFY(object != 0);
1298 object->setProperty("triggerDelete", true);
1303 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1304 QObject *object = component.create();
1305 QVERIFY(object != 0);
1306 object->setProperty("triggerDelete", true);
1312 Test that extended object properties can be accessed.
1314 This test a regression where this used to crash. The issue was specificially
1315 for extended objects that did not include a synthesized meta object (so non-root
1316 and no synthesiszed properties).
1318 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1320 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1321 QObject *object = component.create();
1322 QVERIFY(object != 0);
1327 Test file/lineNumbers for binding/Script errors.
1329 void tst_qdeclarativeecmascript::scriptErrors()
1331 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1332 QString url = component.url().toString();
1334 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1335 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1336 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1337 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1338 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1339 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1340 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1341 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1343 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1344 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1345 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1346 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1347 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1348 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1349 QVERIFY(object != 0);
1351 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1352 emit object->basicSignal();
1354 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1355 emit object->anotherBasicSignal();
1357 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1358 emit object->thirdBasicSignal();
1364 Test file/lineNumbers for inline functions.
1366 void tst_qdeclarativeecmascript::functionErrors()
1368 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1369 QString url = component.url().toString();
1371 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1373 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1375 QObject *object = component.create();
1376 QVERIFY(object != 0);
1379 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1380 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1381 url = componentTwo.url().toString();
1382 object = componentTwo.create();
1383 QVERIFY(object != 0);
1385 QString srpname = object->property("srp_name").toString();
1387 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1388 QLatin1String(" is not a function");
1389 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1390 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1395 Test various errors that can occur when assigning a property from script
1397 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1399 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1401 QString url = component.url().toString();
1403 QObject *object = component.create();
1404 QVERIFY(object != 0);
1406 QCOMPARE(object->property("test1").toBool(), true);
1407 QCOMPARE(object->property("test2").toBool(), true);
1413 Test bindings still work when the reeval is triggered from within
1416 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1418 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1419 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1420 QVERIFY(object != 0);
1422 QCOMPARE(object->property("base").toReal(), 50.);
1423 QCOMPARE(object->property("test1").toReal(), 50.);
1424 QCOMPARE(object->property("test2").toReal(), 50.);
1426 object->basicSignal();
1428 QCOMPARE(object->property("base").toReal(), 200.);
1429 QCOMPARE(object->property("test1").toReal(), 200.);
1430 QCOMPARE(object->property("test2").toReal(), 200.);
1432 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1434 QCOMPARE(object->property("base").toReal(), 400.);
1435 QCOMPARE(object->property("test1").toReal(), 400.);
1436 QCOMPARE(object->property("test2").toReal(), 400.);
1442 Test that list properties can be iterated from ECMAScript
1444 void tst_qdeclarativeecmascript::listProperties()
1446 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1447 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1448 QVERIFY(object != 0);
1450 QCOMPARE(object->property("test1").toInt(), 21);
1451 QCOMPARE(object->property("test2").toInt(), 2);
1452 QCOMPARE(object->property("test3").toBool(), true);
1453 QCOMPARE(object->property("test4").toBool(), true);
1458 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1460 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1461 QString url = component.url().toString();
1463 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1465 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1466 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1467 QVERIFY(object != 0);
1469 QCOMPARE(object->property("test").toBool(), false);
1471 MyQmlObject object2;
1472 MyQmlObject object3;
1473 object2.setObjectProperty(&object3);
1474 object->setObjectProperty(&object2);
1476 QCOMPARE(object->property("test").toBool(), true);
1481 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1483 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1484 QString url = component.url().toString();
1486 QString warning = component.url().toString() + ":6: Error: JS exception";
1488 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1489 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1490 QVERIFY(object != 0);
1494 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1496 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1497 QString url = component.url().toString();
1499 QString warning = component.url().toString() + ":5: Error: JS exception";
1501 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1502 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1503 QVERIFY(object != 0);
1507 static int transientErrorsMsgCount = 0;
1508 static void transientErrorsMsgHandler(QtMsgType, const char *)
1510 ++transientErrorsMsgCount;
1513 // Check that transient binding errors are not displayed
1514 void tst_qdeclarativeecmascript::transientErrors()
1517 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1519 transientErrorsMsgCount = 0;
1520 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1522 QObject *object = component.create();
1523 QVERIFY(object != 0);
1525 qInstallMsgHandler(old);
1527 QCOMPARE(transientErrorsMsgCount, 0);
1532 // One binding erroring multiple times, but then resolving
1534 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1536 transientErrorsMsgCount = 0;
1537 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1539 QObject *object = component.create();
1540 QVERIFY(object != 0);
1542 qInstallMsgHandler(old);
1544 QCOMPARE(transientErrorsMsgCount, 0);
1550 // Check that errors during shutdown are minimized
1551 void tst_qdeclarativeecmascript::shutdownErrors()
1553 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1554 QObject *object = component.create();
1555 QVERIFY(object != 0);
1557 transientErrorsMsgCount = 0;
1558 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1562 qInstallMsgHandler(old);
1563 QCOMPARE(transientErrorsMsgCount, 0);
1566 void tst_qdeclarativeecmascript::compositePropertyType()
1568 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1569 QTest::ignoreMessage(QtDebugMsg, "hello world");
1570 QObject *object = qobject_cast<QObject *>(component.create());
1575 void tst_qdeclarativeecmascript::jsObject()
1577 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1578 QObject *object = component.create();
1579 QVERIFY(object != 0);
1581 QCOMPARE(object->property("test").toInt(), 92);
1586 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1589 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1590 QObject *object = component.create();
1591 QVERIFY(object != 0);
1593 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1595 object->setProperty("setUndefined", true);
1597 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1599 object->setProperty("setUndefined", false);
1601 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1606 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1607 QObject *object = component.create();
1608 QVERIFY(object != 0);
1610 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1612 QMetaObject::invokeMethod(object, "doReset");
1614 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1621 void tst_qdeclarativeecmascript::bug1()
1623 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1624 QObject *object = component.create();
1625 QVERIFY(object != 0);
1627 QCOMPARE(object->property("test").toInt(), 14);
1629 object->setProperty("a", 11);
1631 QCOMPARE(object->property("test").toInt(), 3);
1633 object->setProperty("b", true);
1635 QCOMPARE(object->property("test").toInt(), 9);
1640 void tst_qdeclarativeecmascript::bug2()
1642 QDeclarativeComponent component(&engine);
1643 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1645 QObject *object = component.create();
1646 QVERIFY(object != 0);
1651 // Don't crash in createObject when the component has errors.
1652 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1654 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1655 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1656 QVERIFY(object != 0);
1658 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1659 QMetaObject::invokeMethod(object, "dontCrash");
1660 QObject *created = object->objectProperty();
1661 QVERIFY(created == 0);
1667 void tst_qdeclarativeecmascript::regExpBug()
1669 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1670 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1671 QVERIFY(object != 0);
1672 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1676 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1678 QString functionSource = QLatin1String("(function(object) { return ") +
1679 QLatin1String(source) + QLatin1String(" })");
1681 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1684 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1685 if (function.IsEmpty())
1687 v8::Handle<v8::Value> args[] = { o };
1688 function->Call(engine->global(), 1, args);
1689 return tc.HasCaught();
1692 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1693 const char *source, v8::Handle<v8::Value> result)
1695 QString functionSource = QLatin1String("(function(object) { return ") +
1696 QLatin1String(source) + QLatin1String(" })");
1698 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1701 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1702 if (function.IsEmpty())
1704 v8::Handle<v8::Value> args[] = { o };
1706 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1711 return value->StrictEquals(result);
1714 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1717 QString functionSource = QLatin1String("(function(object) { return ") +
1718 QLatin1String(source) + QLatin1String(" })");
1720 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1722 return v8::Handle<v8::Value>();
1723 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1724 if (function.IsEmpty())
1725 return v8::Handle<v8::Value>();
1726 v8::Handle<v8::Value> args[] = { o };
1728 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1731 return v8::Handle<v8::Value>();
1735 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1736 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1737 #define EVALUATE(source) evaluate(engine, object, source)
1739 void tst_qdeclarativeecmascript::callQtInvokables()
1741 MyInvokableObject o;
1743 QDeclarativeEngine qmlengine;
1744 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1746 QV8Engine *engine = ep->v8engine();
1748 v8::HandleScope handle_scope;
1749 v8::Context::Scope scope(engine->context());
1751 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1753 // Non-existent methods
1755 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1756 QCOMPARE(o.error(), false);
1757 QCOMPARE(o.invoked(), -1);
1758 QCOMPARE(o.actuals().count(), 0);
1761 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1762 QCOMPARE(o.error(), false);
1763 QCOMPARE(o.invoked(), -1);
1764 QCOMPARE(o.actuals().count(), 0);
1766 // Insufficient arguments
1768 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1769 QCOMPARE(o.error(), false);
1770 QCOMPARE(o.invoked(), -1);
1771 QCOMPARE(o.actuals().count(), 0);
1774 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1775 QCOMPARE(o.error(), false);
1776 QCOMPARE(o.invoked(), -1);
1777 QCOMPARE(o.actuals().count(), 0);
1779 // Excessive arguments
1781 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1782 QCOMPARE(o.error(), false);
1783 QCOMPARE(o.invoked(), 8);
1784 QCOMPARE(o.actuals().count(), 1);
1785 QCOMPARE(o.actuals().at(0), QVariant(10));
1788 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1789 QCOMPARE(o.error(), false);
1790 QCOMPARE(o.invoked(), 9);
1791 QCOMPARE(o.actuals().count(), 2);
1792 QCOMPARE(o.actuals().at(0), QVariant(10));
1793 QCOMPARE(o.actuals().at(1), QVariant(11));
1795 // Test return types
1797 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1798 QCOMPARE(o.error(), false);
1799 QCOMPARE(o.invoked(), 0);
1800 QCOMPARE(o.actuals().count(), 0);
1803 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1804 QCOMPARE(o.error(), false);
1805 QCOMPARE(o.invoked(), 1);
1806 QCOMPARE(o.actuals().count(), 0);
1809 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1810 QCOMPARE(o.error(), false);
1811 QCOMPARE(o.invoked(), 2);
1812 QCOMPARE(o.actuals().count(), 0);
1816 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1817 QVERIFY(!ret.IsEmpty());
1818 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1819 QCOMPARE(o.error(), false);
1820 QCOMPARE(o.invoked(), 3);
1821 QCOMPARE(o.actuals().count(), 0);
1826 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1827 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1828 QCOMPARE(o.error(), false);
1829 QCOMPARE(o.invoked(), 4);
1830 QCOMPARE(o.actuals().count(), 0);
1834 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1835 QCOMPARE(o.error(), false);
1836 QCOMPARE(o.invoked(), 5);
1837 QCOMPARE(o.actuals().count(), 0);
1841 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1842 QVERIFY(ret->IsString());
1843 QCOMPARE(engine->toString(ret), QString("Hello world"));
1844 QCOMPARE(o.error(), false);
1845 QCOMPARE(o.invoked(), 6);
1846 QCOMPARE(o.actuals().count(), 0);
1850 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1851 QCOMPARE(o.error(), false);
1852 QCOMPARE(o.invoked(), 7);
1853 QCOMPARE(o.actuals().count(), 0);
1857 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1858 QCOMPARE(o.error(), false);
1859 QCOMPARE(o.invoked(), 8);
1860 QCOMPARE(o.actuals().count(), 1);
1861 QCOMPARE(o.actuals().at(0), QVariant(94));
1864 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1865 QCOMPARE(o.error(), false);
1866 QCOMPARE(o.invoked(), 8);
1867 QCOMPARE(o.actuals().count(), 1);
1868 QCOMPARE(o.actuals().at(0), QVariant(94));
1871 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1872 QCOMPARE(o.error(), false);
1873 QCOMPARE(o.invoked(), 8);
1874 QCOMPARE(o.actuals().count(), 1);
1875 QCOMPARE(o.actuals().at(0), QVariant(0));
1878 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1879 QCOMPARE(o.error(), false);
1880 QCOMPARE(o.invoked(), 8);
1881 QCOMPARE(o.actuals().count(), 1);
1882 QCOMPARE(o.actuals().at(0), QVariant(0));
1885 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1886 QCOMPARE(o.error(), false);
1887 QCOMPARE(o.invoked(), 8);
1888 QCOMPARE(o.actuals().count(), 1);
1889 QCOMPARE(o.actuals().at(0), QVariant(0));
1892 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1893 QCOMPARE(o.error(), false);
1894 QCOMPARE(o.invoked(), 8);
1895 QCOMPARE(o.actuals().count(), 1);
1896 QCOMPARE(o.actuals().at(0), QVariant(0));
1899 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1900 QCOMPARE(o.error(), false);
1901 QCOMPARE(o.invoked(), 9);
1902 QCOMPARE(o.actuals().count(), 2);
1903 QCOMPARE(o.actuals().at(0), QVariant(122));
1904 QCOMPARE(o.actuals().at(1), QVariant(9));
1907 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1908 QCOMPARE(o.error(), false);
1909 QCOMPARE(o.invoked(), 10);
1910 QCOMPARE(o.actuals().count(), 1);
1911 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1914 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1915 QCOMPARE(o.error(), false);
1916 QCOMPARE(o.invoked(), 10);
1917 QCOMPARE(o.actuals().count(), 1);
1918 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1921 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1922 QCOMPARE(o.error(), false);
1923 QCOMPARE(o.invoked(), 10);
1924 QCOMPARE(o.actuals().count(), 1);
1925 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1928 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1929 QCOMPARE(o.error(), false);
1930 QCOMPARE(o.invoked(), 10);
1931 QCOMPARE(o.actuals().count(), 1);
1932 QCOMPARE(o.actuals().at(0), QVariant(0));
1935 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1936 QCOMPARE(o.error(), false);
1937 QCOMPARE(o.invoked(), 10);
1938 QCOMPARE(o.actuals().count(), 1);
1939 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1942 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1943 QCOMPARE(o.error(), false);
1944 QCOMPARE(o.invoked(), 10);
1945 QCOMPARE(o.actuals().count(), 1);
1946 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1949 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1950 QCOMPARE(o.error(), false);
1951 QCOMPARE(o.invoked(), 11);
1952 QCOMPARE(o.actuals().count(), 1);
1953 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1956 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1957 QCOMPARE(o.error(), false);
1958 QCOMPARE(o.invoked(), 11);
1959 QCOMPARE(o.actuals().count(), 1);
1960 QCOMPARE(o.actuals().at(0), QVariant("19"));
1964 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1965 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1966 QCOMPARE(o.error(), false);
1967 QCOMPARE(o.invoked(), 11);
1968 QCOMPARE(o.actuals().count(), 1);
1969 QCOMPARE(o.actuals().at(0), QVariant(expected));
1973 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1974 QCOMPARE(o.error(), false);
1975 QCOMPARE(o.invoked(), 11);
1976 QCOMPARE(o.actuals().count(), 1);
1977 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1980 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1981 QCOMPARE(o.error(), false);
1982 QCOMPARE(o.invoked(), 11);
1983 QCOMPARE(o.actuals().count(), 1);
1984 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1987 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1988 QCOMPARE(o.error(), false);
1989 QCOMPARE(o.invoked(), 12);
1990 QCOMPARE(o.actuals().count(), 1);
1991 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1994 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1995 QCOMPARE(o.error(), false);
1996 QCOMPARE(o.invoked(), 12);
1997 QCOMPARE(o.actuals().count(), 1);
1998 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2001 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
2002 QCOMPARE(o.error(), false);
2003 QCOMPARE(o.invoked(), 12);
2004 QCOMPARE(o.actuals().count(), 1);
2005 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2008 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
2009 QCOMPARE(o.error(), false);
2010 QCOMPARE(o.invoked(), 12);
2011 QCOMPARE(o.actuals().count(), 1);
2012 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2015 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
2016 QCOMPARE(o.error(), false);
2017 QCOMPARE(o.invoked(), 12);
2018 QCOMPARE(o.actuals().count(), 1);
2019 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
2022 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
2023 QCOMPARE(o.error(), false);
2024 QCOMPARE(o.invoked(), 12);
2025 QCOMPARE(o.actuals().count(), 1);
2026 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
2029 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
2030 QCOMPARE(o.error(), false);
2031 QCOMPARE(o.invoked(), 13);
2032 QCOMPARE(o.actuals().count(), 1);
2033 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2036 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
2037 QCOMPARE(o.error(), false);
2038 QCOMPARE(o.invoked(), 13);
2039 QCOMPARE(o.actuals().count(), 1);
2040 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2043 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
2044 QCOMPARE(o.error(), false);
2045 QCOMPARE(o.invoked(), 13);
2046 QCOMPARE(o.actuals().count(), 1);
2047 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2050 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
2051 QCOMPARE(o.error(), false);
2052 QCOMPARE(o.invoked(), 13);
2053 QCOMPARE(o.actuals().count(), 1);
2054 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2057 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
2058 QCOMPARE(o.error(), false);
2059 QCOMPARE(o.invoked(), 13);
2060 QCOMPARE(o.actuals().count(), 1);
2061 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
2064 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
2065 QCOMPARE(o.error(), false);
2066 QCOMPARE(o.invoked(), 14);
2067 QCOMPARE(o.actuals().count(), 1);
2068 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
2071 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
2072 QCOMPARE(o.error(), false);
2073 QCOMPARE(o.invoked(), 14);
2074 QCOMPARE(o.actuals().count(), 1);
2075 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
2078 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
2079 QCOMPARE(o.error(), false);
2080 QCOMPARE(o.invoked(), 14);
2081 QCOMPARE(o.actuals().count(), 1);
2082 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
2085 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
2086 QCOMPARE(o.error(), false);
2087 QCOMPARE(o.invoked(), 14);
2088 QCOMPARE(o.actuals().count(), 1);
2089 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
2092 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
2093 QCOMPARE(o.error(), false);
2094 QCOMPARE(o.invoked(), 15);
2095 QCOMPARE(o.actuals().count(), 2);
2096 QCOMPARE(o.actuals().at(0), QVariant(4));
2097 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
2100 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
2101 QCOMPARE(o.error(), false);
2102 QCOMPARE(o.invoked(), 15);
2103 QCOMPARE(o.actuals().count(), 2);
2104 QCOMPARE(o.actuals().at(0), QVariant(8));
2105 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
2108 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
2109 QCOMPARE(o.error(), false);
2110 QCOMPARE(o.invoked(), 15);
2111 QCOMPARE(o.actuals().count(), 2);
2112 QCOMPARE(o.actuals().at(0), QVariant(3));
2113 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
2116 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
2117 QCOMPARE(o.error(), false);
2118 QCOMPARE(o.invoked(), 15);
2119 QCOMPARE(o.actuals().count(), 2);
2120 QCOMPARE(o.actuals().at(0), QVariant(44));
2121 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
2124 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
2125 QCOMPARE(o.error(), false);
2126 QCOMPARE(o.invoked(), -1);
2127 QCOMPARE(o.actuals().count(), 0);
2130 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
2131 QCOMPARE(o.error(), false);
2132 QCOMPARE(o.invoked(), 16);
2133 QCOMPARE(o.actuals().count(), 1);
2134 QCOMPARE(o.actuals().at(0), QVariant(10));
2137 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
2138 QCOMPARE(o.error(), false);
2139 QCOMPARE(o.invoked(), 17);
2140 QCOMPARE(o.actuals().count(), 2);
2141 QCOMPARE(o.actuals().at(0), QVariant(10));
2142 QCOMPARE(o.actuals().at(1), QVariant(11));
2145 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2146 QCOMPARE(o.error(), false);
2147 QCOMPARE(o.invoked(), 18);
2148 QCOMPARE(o.actuals().count(), 1);
2149 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2152 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2153 QCOMPARE(o.error(), false);
2154 QCOMPARE(o.invoked(), 19);
2155 QCOMPARE(o.actuals().count(), 1);
2156 QCOMPARE(o.actuals().at(0), QVariant(9));
2159 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2160 QCOMPARE(o.error(), false);
2161 QCOMPARE(o.invoked(), 20);
2162 QCOMPARE(o.actuals().count(), 2);
2163 QCOMPARE(o.actuals().at(0), QVariant(10));
2164 QCOMPARE(o.actuals().at(1), QVariant(19));
2167 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2168 QCOMPARE(o.error(), false);
2169 QCOMPARE(o.invoked(), 20);
2170 QCOMPARE(o.actuals().count(), 2);
2171 QCOMPARE(o.actuals().at(0), QVariant(10));
2172 QCOMPARE(o.actuals().at(1), QVariant(13));
2175 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2176 QCOMPARE(o.error(), false);
2177 QCOMPARE(o.invoked(), -3);
2178 QCOMPARE(o.actuals().count(), 1);
2179 QCOMPARE(o.actuals().at(0), QVariant(9));
2182 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2183 QCOMPARE(o.error(), false);
2184 QCOMPARE(o.invoked(), 21);
2185 QCOMPARE(o.actuals().count(), 2);
2186 QCOMPARE(o.actuals().at(0), QVariant(9));
2187 QCOMPARE(o.actuals().at(1), QVariant());
2190 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2191 QCOMPARE(o.error(), false);
2192 QCOMPARE(o.invoked(), 21);
2193 QCOMPARE(o.actuals().count(), 2);
2194 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2195 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2198 // QTBUG-13047 (check that you can pass registered object types as args)
2199 void tst_qdeclarativeecmascript::invokableObjectArg()
2201 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2203 QObject *o = component.create();
2205 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2207 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2212 // QTBUG-13047 (check that you can return registered object types from methods)
2213 void tst_qdeclarativeecmascript::invokableObjectRet()
2215 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2217 QObject *o = component.create();
2219 QCOMPARE(o->property("test").toBool(), true);
2224 void tst_qdeclarativeecmascript::listToVariant()
2226 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2228 MyQmlContainer container;
2230 QDeclarativeContext context(engine.rootContext());
2231 context.setContextObject(&container);
2233 QObject *object = component.create(&context);
2234 QVERIFY(object != 0);
2236 QVariant v = object->property("test");
2237 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2238 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2244 Q_DECLARE_METATYPE(QDeclarativeListProperty<MyQmlObject>)
2245 void tst_qdeclarativeecmascript::listAssignment()
2247 QDeclarativeComponent component(&engine, TEST_FILE("listAssignment.qml"));
2248 QObject *obj = component.create();
2249 QCOMPARE(obj->property("list1length").toInt(), 2);
2250 QDeclarativeListProperty<MyQmlObject> list1 = obj->property("list1").value<QDeclarativeListProperty<MyQmlObject> >();
2251 QDeclarativeListProperty<MyQmlObject> list2 = obj->property("list2").value<QDeclarativeListProperty<MyQmlObject> >();
2252 QCOMPARE(list1.count(&list1), list2.count(&list2));
2253 QCOMPARE(list1.at(&list1, 0), list2.at(&list2, 0));
2254 QCOMPARE(list1.at(&list1, 1), list2.at(&list2, 1));
2259 void tst_qdeclarativeecmascript::multiEngineObject()
2262 obj.setStringProperty("Howdy planet");
2264 QDeclarativeEngine e1;
2265 e1.rootContext()->setContextProperty("thing", &obj);
2266 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2268 QDeclarativeEngine e2;
2269 e2.rootContext()->setContextProperty("thing", &obj);
2270 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2272 QObject *o1 = c1.create();
2273 QObject *o2 = c2.create();
2275 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2276 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2282 // Test that references to QObjects are cleanup when the object is destroyed
2283 void tst_qdeclarativeecmascript::deletedObject()
2285 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2287 QObject *object = component.create();
2289 QCOMPARE(object->property("test1").toBool(), true);
2290 QCOMPARE(object->property("test2").toBool(), true);
2291 QCOMPARE(object->property("test3").toBool(), true);
2292 QCOMPARE(object->property("test4").toBool(), true);
2297 void tst_qdeclarativeecmascript::attachedPropertyScope()
2299 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2301 QObject *object = component.create();
2302 QVERIFY(object != 0);
2304 MyQmlAttachedObject *attached =
2305 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2306 QVERIFY(attached != 0);
2308 QCOMPARE(object->property("value2").toInt(), 0);
2310 attached->emitMySignal();
2312 QCOMPARE(object->property("value2").toInt(), 9);
2317 void tst_qdeclarativeecmascript::scriptConnect()
2320 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2322 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2323 QVERIFY(object != 0);
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);
2333 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2335 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2336 QVERIFY(object != 0);
2338 QCOMPARE(object->property("test").toBool(), false);
2339 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2340 QCOMPARE(object->property("test").toBool(), true);
2346 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2348 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2349 QVERIFY(object != 0);
2351 QCOMPARE(object->property("test").toBool(), false);
2352 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2353 QCOMPARE(object->property("test").toBool(), true);
2359 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2361 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2362 QVERIFY(object != 0);
2364 QCOMPARE(object->methodCalled(), false);
2365 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2366 QCOMPARE(object->methodCalled(), true);
2372 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2374 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2375 QVERIFY(object != 0);
2377 QCOMPARE(object->methodCalled(), false);
2378 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2379 QCOMPARE(object->methodCalled(), true);
2385 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2387 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2388 QVERIFY(object != 0);
2390 QCOMPARE(object->property("test").toInt(), 0);
2391 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2392 QCOMPARE(object->property("test").toInt(), 2);
2398 void tst_qdeclarativeecmascript::scriptDisconnect()
2401 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2403 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2404 QVERIFY(object != 0);
2406 QCOMPARE(object->property("test").toInt(), 0);
2407 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2408 QCOMPARE(object->property("test").toInt(), 1);
2409 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2410 QCOMPARE(object->property("test").toInt(), 2);
2411 emit object->basicSignal();
2412 QCOMPARE(object->property("test").toInt(), 2);
2413 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2414 QCOMPARE(object->property("test").toInt(), 2);
2420 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2422 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2423 QVERIFY(object != 0);
2425 QCOMPARE(object->property("test").toInt(), 0);
2426 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2427 QCOMPARE(object->property("test").toInt(), 1);
2428 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2429 QCOMPARE(object->property("test").toInt(), 2);
2430 emit object->basicSignal();
2431 QCOMPARE(object->property("test").toInt(), 2);
2432 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2433 QCOMPARE(object->property("test").toInt(), 2);
2439 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2441 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2442 QVERIFY(object != 0);
2444 QCOMPARE(object->property("test").toInt(), 0);
2445 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2446 QCOMPARE(object->property("test").toInt(), 1);
2447 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2448 QCOMPARE(object->property("test").toInt(), 2);
2449 emit object->basicSignal();
2450 QCOMPARE(object->property("test").toInt(), 2);
2451 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2452 QCOMPARE(object->property("test").toInt(), 3);
2457 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2459 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2460 QVERIFY(object != 0);
2462 QCOMPARE(object->property("test").toInt(), 0);
2463 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2464 QCOMPARE(object->property("test").toInt(), 1);
2465 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2466 QCOMPARE(object->property("test").toInt(), 2);
2467 emit object->basicSignal();
2468 QCOMPARE(object->property("test").toInt(), 2);
2469 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2470 QCOMPARE(object->property("test").toInt(), 3);
2476 class OwnershipObject : public QObject
2480 OwnershipObject() { object = new QObject; }
2482 QPointer<QObject> object;
2485 QObject *getObject() { return object; }
2488 void tst_qdeclarativeecmascript::ownership()
2490 OwnershipObject own;
2491 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2492 context->setContextObject(&own);
2495 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2497 QVERIFY(own.object != 0);
2499 QObject *object = component.create(context);
2501 engine.collectGarbage();
2503 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2505 QVERIFY(own.object == 0);
2510 own.object = new QObject(&own);
2513 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2515 QVERIFY(own.object != 0);
2517 QObject *object = component.create(context);
2519 engine.collectGarbage();
2521 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2523 QVERIFY(own.object != 0);
2531 class CppOwnershipReturnValue : public QObject
2535 CppOwnershipReturnValue() : value(0) {}
2536 ~CppOwnershipReturnValue() { delete value; }
2538 Q_INVOKABLE QObject *create() {
2539 value = new QObject;
2540 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2544 Q_INVOKABLE MyQmlObject *createQmlObject() {
2545 MyQmlObject *rv = new MyQmlObject;
2550 QPointer<QObject> value;
2554 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2555 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2557 CppOwnershipReturnValue source;
2560 QDeclarativeEngine engine;
2561 engine.rootContext()->setContextProperty("source", &source);
2563 QVERIFY(source.value == 0);
2565 QDeclarativeComponent component(&engine);
2566 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2568 QObject *object = component.create();
2570 QVERIFY(object != 0);
2571 QVERIFY(source.value != 0);
2576 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2578 QVERIFY(source.value != 0);
2582 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2584 CppOwnershipReturnValue source;
2587 QDeclarativeEngine engine;
2588 engine.rootContext()->setContextProperty("source", &source);
2590 QVERIFY(source.value == 0);
2592 QDeclarativeComponent component(&engine);
2593 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2595 QObject *object = component.create();
2597 QVERIFY(object != 0);
2598 QVERIFY(source.value != 0);
2603 engine.collectGarbage();
2604 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2606 QVERIFY(source.value == 0);
2609 class QListQObjectMethodsObject : public QObject
2613 QListQObjectMethodsObject() {
2614 m_objects.append(new MyQmlObject());
2615 m_objects.append(new MyQmlObject());
2618 ~QListQObjectMethodsObject() {
2619 qDeleteAll(m_objects);
2623 QList<QObject *> getObjects() { return m_objects; }
2626 QList<QObject *> m_objects;
2629 // Tests that returning a QList<QObject*> from a method works
2630 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2632 QListQObjectMethodsObject obj;
2633 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2634 context->setContextObject(&obj);
2636 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2638 QObject *object = component.create(context);
2640 QCOMPARE(object->property("test").toInt(), 2);
2641 QCOMPARE(object->property("test2").toBool(), true);
2648 void tst_qdeclarativeecmascript::strictlyEquals()
2650 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2652 QObject *object = component.create();
2653 QVERIFY(object != 0);
2655 QCOMPARE(object->property("test1").toBool(), true);
2656 QCOMPARE(object->property("test2").toBool(), true);
2657 QCOMPARE(object->property("test3").toBool(), true);
2658 QCOMPARE(object->property("test4").toBool(), true);
2659 QCOMPARE(object->property("test5").toBool(), true);
2660 QCOMPARE(object->property("test6").toBool(), true);
2661 QCOMPARE(object->property("test7").toBool(), true);
2662 QCOMPARE(object->property("test8").toBool(), true);
2667 void tst_qdeclarativeecmascript::compiled()
2669 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2671 QObject *object = component.create();
2672 QVERIFY(object != 0);
2674 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2675 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2676 QCOMPARE(object->property("test3").toBool(), true);
2677 QCOMPARE(object->property("test4").toBool(), false);
2678 QCOMPARE(object->property("test5").toBool(), false);
2679 QCOMPARE(object->property("test6").toBool(), true);
2681 QCOMPARE(object->property("test7").toInt(), 185);
2682 QCOMPARE(object->property("test8").toInt(), 167);
2683 QCOMPARE(object->property("test9").toBool(), true);
2684 QCOMPARE(object->property("test10").toBool(), false);
2685 QCOMPARE(object->property("test11").toBool(), false);
2686 QCOMPARE(object->property("test12").toBool(), true);
2688 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2689 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2690 QCOMPARE(object->property("test15").toBool(), false);
2691 QCOMPARE(object->property("test16").toBool(), true);
2693 QCOMPARE(object->property("test17").toInt(), 5);
2694 QCOMPARE(object->property("test18").toReal(), qreal(176));
2695 QCOMPARE(object->property("test19").toInt(), 7);
2696 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2697 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2698 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2699 QCOMPARE(object->property("test23").toBool(), true);
2700 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2701 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2706 // Test that numbers assigned in bindings as strings work consistently
2707 void tst_qdeclarativeecmascript::numberAssignment()
2709 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2711 QObject *object = component.create();
2712 QVERIFY(object != 0);
2714 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2715 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2716 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2717 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2718 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2720 QCOMPARE(object->property("test5"), QVariant((int)7));
2721 QCOMPARE(object->property("test6"), QVariant((int)7));
2722 QCOMPARE(object->property("test7"), QVariant((int)6));
2723 QCOMPARE(object->property("test8"), QVariant((int)6));
2725 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2726 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2727 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2728 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2733 void tst_qdeclarativeecmascript::propertySplicing()
2735 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2737 QObject *object = component.create();
2738 QVERIFY(object != 0);
2740 QCOMPARE(object->property("test").toBool(), true);
2746 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2748 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2750 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2751 QVERIFY(object != 0);
2753 MyQmlObject::MyType type;
2754 type.value = 0x8971123;
2755 emit object->signalWithUnknownType(type);
2757 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2759 QCOMPARE(result.value, type.value);
2765 void tst_qdeclarativeecmascript::signalWithJSValueInVariant_data()
2767 QTest::addColumn<QString>("expression");
2768 QTest::addColumn<QString>("compare");
2770 QString compareStrict("(function(a, b) { return a === b; })");
2771 QTest::newRow("true") << "true" << compareStrict;
2772 QTest::newRow("undefined") << "undefined" << compareStrict;
2773 QTest::newRow("null") << "null" << compareStrict;
2774 QTest::newRow("123") << "123" << compareStrict;
2775 QTest::newRow("'ciao'") << "'ciao'" << compareStrict;
2777 QString comparePropertiesStrict(
2779 " if (typeof b != 'object')"
2781 " var props = Object.getOwnPropertyNames(b);"
2782 " for (var i = 0; i < props.length; ++i) {"
2783 " var p = props[i];"
2784 " return arguments.callee(a[p], b[p]);"
2787 QTest::newRow("{ foo: 'bar' }") << "({ foo: 'bar' })" << comparePropertiesStrict;
2788 QTest::newRow("[10,20,30]") << "[10,20,30]" << comparePropertiesStrict;
2791 void tst_qdeclarativeecmascript::signalWithJSValueInVariant()
2793 QFETCH(QString, expression);
2794 QFETCH(QString, compare);
2796 QDeclarativeComponent component(&engine, TEST_FILE("signalWithJSValueInVariant.qml"));
2797 QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
2798 QVERIFY(object != 0);
2800 QJSValue value = engine.evaluate(expression);
2801 QVERIFY(!engine.hasUncaughtException());
2802 object->setProperty("expression", expression);
2803 object->setProperty("compare", compare);
2804 object->setProperty("pass", false);
2806 emit object->signalWithVariant(QVariant::fromValue(value));
2807 QVERIFY(object->property("pass").toBool());
2810 void tst_qdeclarativeecmascript::signalWithJSValueInVariant_twoEngines_data()
2812 signalWithJSValueInVariant_data();
2815 void tst_qdeclarativeecmascript::signalWithJSValueInVariant_twoEngines()
2817 QFETCH(QString, expression);
2818 QFETCH(QString, compare);
2820 QDeclarativeComponent component(&engine, TEST_FILE("signalWithJSValueInVariant.qml"));
2821 QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
2822 QVERIFY(object != 0);
2825 QJSValue value = engine2.evaluate(expression);
2826 QVERIFY(!engine2.hasUncaughtException());
2827 object->setProperty("expression", expression);
2828 object->setProperty("compare", compare);
2829 object->setProperty("pass", false);
2831 QTest::ignoreMessage(QtWarningMsg, "JSValue can't be rassigned to an another engine.");
2832 emit object->signalWithVariant(QVariant::fromValue(value));
2833 QVERIFY(!object->property("pass").toBool());
2836 void tst_qdeclarativeecmascript::moduleApi_data()
2838 QTest::addColumn<QUrl>("testfile");
2839 QTest::addColumn<QString>("errorMessage");
2840 QTest::addColumn<QStringList>("warningMessages");
2841 QTest::addColumn<QStringList>("readProperties");
2842 QTest::addColumn<QVariantList>("readExpectedValues");
2843 QTest::addColumn<QStringList>("writeProperties");
2844 QTest::addColumn<QVariantList>("writeValues");
2845 QTest::addColumn<QStringList>("readBackProperties");
2846 QTest::addColumn<QVariantList>("readBackExpectedValues");
2848 QTest::newRow("qobject, register + read + method")
2849 << TEST_FILE("moduleapi/qobjectModuleApi.qml")
2852 << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest"
2853 << "qobjectMinorVersionTest" << "qobjectMajorVersionTest" << "qobjectParentedTest")
2854 << (QVariantList() << 20 << 20 << 1 << 20 << 20 << 26)
2860 QTest::newRow("script, register + read")
2861 << TEST_FILE("moduleapi/scriptModuleApi.qml")
2864 << (QStringList() << "scriptTest")
2865 << (QVariantList() << 13)
2871 QTest::newRow("qobject, caching + read")
2872 << TEST_FILE("moduleapi/qobjectModuleApiCaching.qml")
2875 << (QStringList() << "existingUriTest" << "qobjectParentedTest")
2876 << (QVariantList() << 20 << 26) // 26, shouldn't have incremented to 27.
2882 QTest::newRow("script, caching + read")
2883 << TEST_FILE("moduleapi/scriptModuleApiCaching.qml")
2886 << (QStringList() << "scriptTest")
2887 << (QVariantList() << 13) // 13, shouldn't have incremented to 14.
2893 QTest::newRow("qobject, writing + readonly constraints")
2894 << TEST_FILE("moduleapi/qobjectModuleApiWriting.qml")
2896 << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":14: Error: Cannot assign to read-only property \"qobjectTestProperty\"")))
2897 << (QStringList() << "readOnlyProperty" << "writableProperty")
2898 << (QVariantList() << 20 << 50)
2899 << (QStringList() << "firstProperty" << "writableProperty")
2900 << (QVariantList() << 30 << 30)
2901 << (QStringList() << "readOnlyProperty" << "writableProperty")
2902 << (QVariantList() << 20 << 30);
2904 QTest::newRow("script, writing + readonly constraints")
2905 << TEST_FILE("moduleapi/scriptModuleApiWriting.qml")
2907 << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/scriptModuleApiWriting.qml").toLocalFile() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\"")))
2908 << (QStringList() << "readBack" << "unchanged")
2909 << (QVariantList() << 13 << 42)
2910 << (QStringList() << "firstProperty" << "secondProperty")
2911 << (QVariantList() << 30 << 30)
2912 << (QStringList() << "readBack" << "unchanged")
2913 << (QVariantList() << 30 << 42);
2915 QTest::newRow("qobject module API enum values in JS")
2916 << TEST_FILE("moduleapi/qobjectModuleApiEnums.qml")
2919 << (QStringList() << "enumValue" << "enumMethod")
2920 << (QVariantList() << 42 << 30)
2926 QTest::newRow("qobject, invalid major version fail")
2927 << TEST_FILE("moduleapi/moduleApiMajorVersionFail.qml")
2928 << QString("QDeclarativeComponent: Component is not ready")
2937 QTest::newRow("qobject, invalid minor version fail")
2938 << TEST_FILE("moduleapi/moduleApiMinorVersionFail.qml")
2939 << QString("QDeclarativeComponent: Component is not ready")
2949 void tst_qdeclarativeecmascript::moduleApi()
2951 QFETCH(QUrl, testfile);
2952 QFETCH(QString, errorMessage);
2953 QFETCH(QStringList, warningMessages);
2954 QFETCH(QStringList, readProperties);
2955 QFETCH(QVariantList, readExpectedValues);
2956 QFETCH(QStringList, writeProperties);
2957 QFETCH(QVariantList, writeValues);
2958 QFETCH(QStringList, readBackProperties);
2959 QFETCH(QVariantList, readBackExpectedValues);
2961 QDeclarativeComponent component(&engine, testfile);
2963 if (!errorMessage.isEmpty())
2964 QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData());
2966 if (warningMessages.size())
2967 foreach (const QString &warning, warningMessages)
2968 QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
2970 QObject *object = component.create();
2971 if (!errorMessage.isEmpty()) {
2972 QVERIFY(object == 0);
2974 QVERIFY(object != 0);
2975 for (int i = 0; i < readProperties.size(); ++i)
2976 QCOMPARE(object->property(readProperties.at(i).toAscii().constData()), readExpectedValues.at(i));
2977 for (int i = 0; i < writeProperties.size(); ++i)
2978 QVERIFY(object->setProperty(writeProperties.at(i).toAscii().constData(), writeValues.at(i)));
2979 for (int i = 0; i < readBackProperties.size(); ++i)
2980 QCOMPARE(object->property(readBackProperties.at(i).toAscii().constData()), readBackExpectedValues.at(i));
2985 void tst_qdeclarativeecmascript::importScripts()
2987 QObject *object = 0;
2989 // first, ensure that the required behaviour works.
2990 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2991 object = component.create();
2992 QVERIFY(object != 0);
2993 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2994 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2995 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2996 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2999 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
3000 object = componentTwo.create();
3001 QVERIFY(object != 0);
3002 QCOMPARE(object->property("componentError"), QVariant(5));
3005 // then, ensure that unintended behaviour does not work.
3006 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
3007 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
3008 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3009 object = failOneComponent.create();
3010 QVERIFY(object != 0);
3011 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
3013 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
3014 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
3015 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3016 object = failTwoComponent.create();
3017 QVERIFY(object != 0);
3018 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
3020 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
3021 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
3022 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3023 object = failThreeComponent.create();
3024 QVERIFY(object != 0);
3025 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
3027 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
3028 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
3029 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3030 object = failFourComponent.create();
3031 QVERIFY(object != 0);
3032 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
3034 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
3035 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
3036 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3037 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
3038 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3039 object = failFiveComponent.create();
3040 QVERIFY(object != 0);
3041 QCOMPARE(object->property("componentError"), QVariant(0));
3044 // also, test that importing scripts with .pragma library works as required
3045 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
3046 object = pragmaLibraryComponent.create();
3047 QVERIFY(object != 0);
3048 QCOMPARE(object->property("testValue"), QVariant(31));
3051 // and that .pragma library scripts don't inherit imports from any .qml file
3052 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
3053 object = pragmaLibraryComponentTwo.create();
3054 QVERIFY(object != 0);
3055 QCOMPARE(object->property("testValue"), QVariant(0));
3059 void tst_qdeclarativeecmascript::scarceResources()
3061 QPixmap origPixmap(100, 100);
3062 origPixmap.fill(Qt::blue);
3064 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
3065 ScarceResourceObject *eo = 0;
3066 QObject *object = 0;
3068 // in the following three cases, the instance created from the component
3069 // has a property which is a copy of the scarce resource; hence, the
3070 // resource should NOT be detached prior to deletion of the object instance,
3071 // unless the resource is destroyed explicitly.
3072 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
3073 object = component.create();
3074 QVERIFY(object != 0);
3075 QVERIFY(object->property("scarceResourceCopy").isValid());
3076 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3077 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3078 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3079 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
3082 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
3083 object = componentTwo.create();
3084 QVERIFY(object != 0);
3085 QVERIFY(object->property("scarceResourceCopy").isValid());
3086 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3087 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3088 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3089 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
3092 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
3093 object = componentThree.create();
3094 QVERIFY(object != 0);
3095 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
3096 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3097 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3098 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
3101 // in the following three cases, no other copy should exist in memory,
3102 // and so it should be detached (unless explicitly preserved).
3103 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
3104 object = componentFour.create();
3105 QVERIFY(object != 0);
3106 QVERIFY(object->property("scarceResourceTest").isValid());
3107 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3108 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3109 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3110 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
3113 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
3114 object = componentFive.create();
3115 QVERIFY(object != 0);
3116 QVERIFY(object->property("scarceResourceTest").isValid());
3117 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3118 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3119 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3120 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
3123 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
3124 object = componentSix.create();
3125 QVERIFY(object != 0);
3126 QVERIFY(object->property("scarceResourceTest").isValid());
3127 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3128 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3129 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3130 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
3133 // test that scarce resources are handled correctly for imports
3134 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
3135 object = componentSeven.create();
3136 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
3137 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
3140 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
3141 object = componentEight.create();
3142 QVERIFY(object != 0);
3143 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
3144 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3147 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
3148 object = componentNine.create();
3149 QVERIFY(object != 0);
3150 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
3151 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3152 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
3153 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
3154 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
3155 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
3158 // test that scarce resources are handled properly in signal invocation
3159 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
3160 object = componentTen.create();
3161 QVERIFY(object != 0);
3162 QObject *srsc = object->findChild<QObject*>("srsc");
3164 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
3165 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
3166 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3167 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3168 QMetaObject::invokeMethod(srsc, "testSignal");
3169 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
3170 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
3171 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3172 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
3173 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
3174 QVERIFY(srsc->property("scarceResourceCopy").isValid());
3175 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3176 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3177 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
3178 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3181 // test that scarce resources are handled properly from js functions in qml files
3182 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
3183 object = componentEleven.create();
3184 QVERIFY(object != 0);
3185 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3186 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3187 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3188 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3189 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
3190 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3191 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3192 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
3193 QMetaObject::invokeMethod(object, "releaseScarceResource");
3194 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
3195 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3196 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3197 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3200 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
3201 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
3202 object = componentTwelve.create();
3203 QVERIFY(object != 0);
3204 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3205 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3206 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3207 QString srp_name = object->property("srp_name").toString();
3208 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
3209 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
3210 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3211 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
3212 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3213 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3214 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3218 void tst_qdeclarativeecmascript::propertyChangeSlots()
3220 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
3221 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
3222 QObject *object = component.create();
3223 QVERIFY(object != 0);
3226 // ensure that invalid property names fail properly.
3227 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3228 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
3229 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
3230 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
3231 object = e1.create();
3232 QVERIFY(object == 0);
3235 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3236 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
3237 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
3238 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
3239 object = e2.create();
3240 QVERIFY(object == 0);
3243 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3244 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
3245 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
3246 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
3247 object = e3.create();
3248 QVERIFY(object == 0);
3251 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3252 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
3253 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
3254 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
3255 object = e4.create();
3256 QVERIFY(object == 0);
3260 // Ensure that QObject type conversion works on binding assignment
3261 void tst_qdeclarativeecmascript::elementAssign()
3263 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
3265 QObject *object = component.create();
3266 QVERIFY(object != 0);
3268 QCOMPARE(object->property("test").toBool(), true);
3274 void tst_qdeclarativeecmascript::objectPassThroughSignals()
3276 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
3278 QObject *object = component.create();
3279 QVERIFY(object != 0);
3281 QCOMPARE(object->property("test").toBool(), true);
3287 void tst_qdeclarativeecmascript::booleanConversion()
3289 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
3291 QObject *object = component.create();
3292 QVERIFY(object != 0);
3294 QCOMPARE(object->property("test_true1").toBool(), true);
3295 QCOMPARE(object->property("test_true2").toBool(), true);
3296 QCOMPARE(object->property("test_true3").toBool(), true);
3297 QCOMPARE(object->property("test_true4").toBool(), true);
3298 QCOMPARE(object->property("test_true5").toBool(), true);
3300 QCOMPARE(object->property("test_false1").toBool(), false);
3301 QCOMPARE(object->property("test_false2").toBool(), false);
3302 QCOMPARE(object->property("test_false3").toBool(), false);
3307 void tst_qdeclarativeecmascript::handleReferenceManagement()
3312 // Linear QObject reference
3313 QDeclarativeEngine hrmEngine;
3314 QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.object.1.qml"));
3315 QObject *object = component.create();
3316 QVERIFY(object != 0);
3317 CircularReferenceObject *cro = object->findChild<CircularReferenceObject*>("cro");
3318 cro->setDtorCount(&dtorCount);
3319 QMetaObject::invokeMethod(object, "createReference");
3320 QMetaObject::invokeMethod(object, "performGc");
3321 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3322 QCOMPARE(dtorCount, 0); // second has JS ownership, kept alive by first's reference
3324 hrmEngine.collectGarbage();
3325 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3326 QCOMPARE(dtorCount, 3);
3331 // Circular QObject reference
3332 QDeclarativeEngine hrmEngine;
3333 QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.object.2.qml"));
3334 QObject *object = component.create();
3335 QVERIFY(object != 0);
3336 CircularReferenceObject *cro = object->findChild<CircularReferenceObject*>("cro");
3337 cro->setDtorCount(&dtorCount);
3338 QMetaObject::invokeMethod(object, "circularReference");
3339 QMetaObject::invokeMethod(object, "performGc");
3340 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3341 QCOMPARE(dtorCount, 2); // both should be cleaned up, since circular references shouldn't keep alive.
3343 hrmEngine.collectGarbage();
3344 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3345 QCOMPARE(dtorCount, 3);
3350 // Linear handle reference
3351 QDeclarativeEngine hrmEngine;
3352 QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3353 QObject *object = component.create();
3354 QVERIFY(object != 0);
3355 CircularReferenceHandle *crh = object->findChild<CircularReferenceHandle*>("crh");
3357 crh->setDtorCount(&dtorCount);
3358 QMetaObject::invokeMethod(object, "createReference");
3359 CircularReferenceHandle *first = object->property("first").value<CircularReferenceHandle*>();
3360 CircularReferenceHandle *second = object->property("second").value<CircularReferenceHandle*>();
3361 QVERIFY(first != 0);
3362 QVERIFY(second != 0);
3363 first->addReference(QDeclarativeData::get(second)->v8object); // create reference
3364 // now we have to reparent second and make second owned by JS.
3365 second->setParent(0);
3366 QDeclarativeEngine::setObjectOwnership(second, QDeclarativeEngine::JavaScriptOwnership);
3367 QMetaObject::invokeMethod(object, "performGc");
3368 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3369 QCOMPARE(dtorCount, 0); // due to reference from first to second, second shouldn't be collected.
3371 hrmEngine.collectGarbage();
3372 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3373 QCOMPARE(dtorCount, 3);
3378 // Circular handle reference
3379 QDeclarativeEngine hrmEngine;
3380 QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.handle.2.qml"));
3381 QObject *object = component.create();
3382 QVERIFY(object != 0);
3383 CircularReferenceHandle *crh = object->findChild<CircularReferenceHandle*>("crh");
3385 crh->setDtorCount(&dtorCount);
3386 QMetaObject::invokeMethod(object, "circularReference");
3387 CircularReferenceHandle *first = object->property("first").value<CircularReferenceHandle*>();
3388 CircularReferenceHandle *second = object->property("second").value<CircularReferenceHandle*>();
3389 QVERIFY(first != 0);
3390 QVERIFY(second != 0);
3391 first->addReference(QDeclarativeData::get(second)->v8object); // create circular reference
3392 second->addReference(QDeclarativeData::get(first)->v8object); // note: must be weak.
3393 // now we have to reparent and change ownership.
3394 first->setParent(0);
3395 second->setParent(0);
3396 QDeclarativeEngine::setObjectOwnership(first, QDeclarativeEngine::JavaScriptOwnership);
3397 QDeclarativeEngine::setObjectOwnership(second, QDeclarativeEngine::JavaScriptOwnership);
3398 QMetaObject::invokeMethod(object, "performGc");
3399 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3400 QCOMPARE(dtorCount, 2); // despite circular references, both will be collected.
3402 hrmEngine.collectGarbage();
3403 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3404 QCOMPARE(dtorCount, 3);
3409 // multiple engine interaction - linear reference
3410 QDeclarativeEngine hrmEngine1;
3411 QDeclarativeEngine hrmEngine2;
3412 QDeclarativeComponent component1(&hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3413 QDeclarativeComponent component2(&hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3414 QObject *object1 = component1.create();
3415 QObject *object2 = component2.create();
3416 QVERIFY(object1 != 0);
3417 QVERIFY(object2 != 0);
3418 CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
3419 CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
3422 crh1->setDtorCount(&dtorCount);
3423 crh2->setDtorCount(&dtorCount);
3424 QMetaObject::invokeMethod(object1, "createReference");
3425 QMetaObject::invokeMethod(object2, "createReference");
3426 CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
3427 CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
3428 CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
3429 CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
3430 QVERIFY(first1 != 0);
3431 QVERIFY(second1 != 0);
3432 QVERIFY(first2 != 0);
3433 QVERIFY(second2 != 0);
3434 first1->addReference(QDeclarativeData::get(second2)->v8object); // create reference across engines
3435 // now we have to reparent second2 and make second2 owned by JS.
3436 second2->setParent(0);
3437 QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
3438 QMetaObject::invokeMethod(object1, "performGc");
3439 QMetaObject::invokeMethod(object2, "performGc");
3440 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3441 QCOMPARE(dtorCount, 0); // due to reference from first1 to second2, second2 shouldn't be collected.
3444 hrmEngine1.collectGarbage();
3445 hrmEngine2.collectGarbage();
3446 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3447 QCOMPARE(dtorCount, 6);
3452 // multiple engine interaction - circular reference
3453 QDeclarativeEngine hrmEngine1;
3454 QDeclarativeEngine hrmEngine2;
3455 QDeclarativeComponent component1(&hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3456 QDeclarativeComponent component2(&hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3457 QObject *object1 = component1.create();
3458 QObject *object2 = component2.create();
3459 QVERIFY(object1 != 0);
3460 QVERIFY(object2 != 0);
3461 CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
3462 CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
3465 crh1->setDtorCount(&dtorCount);
3466 crh2->setDtorCount(&dtorCount);
3467 QMetaObject::invokeMethod(object1, "createReference");
3468 QMetaObject::invokeMethod(object2, "createReference");
3469 CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
3470 CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
3471 CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
3472 CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
3473 QVERIFY(first1 != 0);
3474 QVERIFY(second1 != 0);
3475 QVERIFY(first2 != 0);
3476 QVERIFY(second2 != 0);
3477 first1->addReference(QDeclarativeData::get(second1)->v8object); // create linear reference within engine1
3478 second1->addReference(QDeclarativeData::get(second2)->v8object); // create linear reference across engines
3479 second2->addReference(QDeclarativeData::get(first2)->v8object); // create linear reference within engine2
3480 first2->addReference(QDeclarativeData::get(first1)->v8object); // close the loop - circular ref across engines
3481 // now we have to reparent and change ownership to JS.
3482 first1->setParent(0);
3483 second1->setParent(0);
3484 first2->setParent(0);
3485 second2->setParent(0);
3486 QDeclarativeEngine::setObjectOwnership(first1, QDeclarativeEngine::JavaScriptOwnership);
3487 QDeclarativeEngine::setObjectOwnership(second1, QDeclarativeEngine::JavaScriptOwnership);
3488 QDeclarativeEngine::setObjectOwnership(first2, QDeclarativeEngine::JavaScriptOwnership);
3489 QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
3490 QMetaObject::invokeMethod(object1, "performGc");
3491 QMetaObject::invokeMethod(object2, "performGc");
3492 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3493 QCOMPARE(dtorCount, 4); // circular references shouldn't keep them alive.
3496 hrmEngine1.collectGarbage();
3497 hrmEngine2.collectGarbage();
3498 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3499 QCOMPARE(dtorCount, 6);
3504 // multiple engine interaction - linear reference with engine deletion
3505 QDeclarativeEngine *hrmEngine1 = new QDeclarativeEngine;
3506 QDeclarativeEngine *hrmEngine2 = new QDeclarativeEngine;
3507 QDeclarativeComponent component1(hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3508 QDeclarativeComponent component2(hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3509 QObject *object1 = component1.create();
3510 QObject *object2 = component2.create();
3511 QVERIFY(object1 != 0);
3512 QVERIFY(object2 != 0);
3513 CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
3514 CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
3517 crh1->setDtorCount(&dtorCount);
3518 crh2->setDtorCount(&dtorCount);
3519 QMetaObject::invokeMethod(object1, "createReference");
3520 QMetaObject::invokeMethod(object2, "createReference");
3521 CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
3522 CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
3523 CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
3524 CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
3525 QVERIFY(first1 != 0);
3526 QVERIFY(second1 != 0);
3527 QVERIFY(first2 != 0);
3528 QVERIFY(second2 != 0);
3529 first1->addReference(QDeclarativeData::get(second1)->v8object); // create linear reference within engine1
3530 second1->addReference(QDeclarativeData::get(second2)->v8object); // create linear reference across engines
3531 second2->addReference(QDeclarativeData::get(first2)->v8object); // create linear reference within engine2
3532 // now we have to reparent and change ownership to JS.
3533 first1->setParent(crh1);
3534 second1->setParent(0);
3535 first2->setParent(0);
3536 second2->setParent(0);
3537 QDeclarativeEngine::setObjectOwnership(second1, QDeclarativeEngine::JavaScriptOwnership);
3538 QDeclarativeEngine::setObjectOwnership(first2, QDeclarativeEngine::JavaScriptOwnership);
3539 QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
3540 QMetaObject::invokeMethod(object1, "performGc");
3541 QMetaObject::invokeMethod(object2, "performGc");
3542 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3543 QCOMPARE(dtorCount, 0);
3545 QMetaObject::invokeMethod(object1, "performGc");
3546 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3547 QCOMPARE(dtorCount, 0);
3550 hrmEngine1->collectGarbage();
3551 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3552 QCOMPARE(dtorCount, 6);
3557 // Test that assigning a null object works
3558 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
3559 void tst_qdeclarativeecmascript::nullObjectBinding()
3561 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
3563 QObject *object = component.create();
3564 QVERIFY(object != 0);
3566 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3571 // Test that bindings don't evaluate once the engine has been destroyed
3572 void tst_qdeclarativeecmascript::deletedEngine()
3574 QDeclarativeEngine *engine = new QDeclarativeEngine;
3575 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3577 QObject *object = component.create();
3578 QVERIFY(object != 0);
3580 QCOMPARE(object->property("a").toInt(), 39);
3581 object->setProperty("b", QVariant(9));
3582 QCOMPARE(object->property("a").toInt(), 117);
3586 QCOMPARE(object->property("a").toInt(), 117);
3587 object->setProperty("b", QVariant(10));
3588 QCOMPARE(object->property("a").toInt(), 117);
3593 // Test the crashing part of QTBUG-9705
3594 void tst_qdeclarativeecmascript::libraryScriptAssert()
3596 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3598 QObject *object = component.create();
3599 QVERIFY(object != 0);
3604 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3606 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3608 QObject *object = component.create();
3609 QVERIFY(object != 0);
3611 QCOMPARE(object->property("test1").toInt(), 10);
3612 QCOMPARE(object->property("test2").toInt(), 11);
3614 object->setProperty("runTest", true);
3616 QCOMPARE(object->property("test1"), QVariant());
3617 QCOMPARE(object->property("test2"), QVariant());
3623 void tst_qdeclarativeecmascript::qtbug_9792()
3625 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3627 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3629 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3630 QVERIFY(object != 0);
3632 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3633 object->basicSignal();
3637 transientErrorsMsgCount = 0;
3638 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3640 object->basicSignal();
3642 qInstallMsgHandler(old);
3644 QCOMPARE(transientErrorsMsgCount, 0);
3649 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3650 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3652 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3654 QObject *o = component.create();
3657 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3658 QVERIFY(nested != 0);
3660 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3663 nested = qvariant_cast<QObject *>(o->property("object"));
3664 QVERIFY(nested == 0);
3666 // If the bug is present, the next line will crash
3670 // Test that we shut down without stupid warnings
3671 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3674 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3676 QObject *o = component.create();
3678 transientErrorsMsgCount = 0;
3679 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3683 qInstallMsgHandler(old);
3685 QCOMPARE(transientErrorsMsgCount, 0);
3690 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3692 QObject *o = component.create();
3694 transientErrorsMsgCount = 0;
3695 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3699 qInstallMsgHandler(old);
3701 QCOMPARE(transientErrorsMsgCount, 0);
3705 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3708 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3710 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3713 QVERIFY(o->objectProperty() != 0);
3715 o->setProperty("runTest", true);
3717 QVERIFY(o->objectProperty() == 0);
3723 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3725 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3728 QVERIFY(o->objectProperty() == 0);
3734 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3736 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3738 QString url = component.url().toString();
3739 QString warning = url + ":4: Unable to assign a function to a property.";
3740 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3742 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3745 QVERIFY(!o->property("a").isValid());
3750 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3752 QFETCH(QString, triggerProperty);
3754 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3755 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3757 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3759 QVERIFY(!o->property("a").isValid());
3761 o->setProperty("aNumber", QVariant(5));
3762 o->setProperty(triggerProperty.toUtf8().constData(), true);
3763 QCOMPARE(o->property("a"), QVariant(50));
3765 o->setProperty("aNumber", QVariant(10));
3766 QCOMPARE(o->property("a"), QVariant(100));
3771 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3773 QTest::addColumn<QString>("triggerProperty");
3775 QTest::newRow("assign to property") << "assignToProperty";
3776 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3778 QTest::newRow("assign to value type") << "assignToValueType";
3780 QTest::newRow("use 'this'") << "assignWithThis";
3781 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3784 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3786 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3787 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3789 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3791 QVERIFY(!o->property("a").isValid());
3793 o->setProperty("assignFuncWithoutReturn", true);
3794 QVERIFY(!o->property("a").isValid());
3796 QString url = component.url().toString();
3797 QString warning = url + ":67: Unable to assign QString to int";
3798 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3799 o->setProperty("assignWrongType", true);
3801 warning = url + ":71: Unable to assign QString to int";
3802 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3803 o->setProperty("assignWrongTypeToValueType", true);
3808 void tst_qdeclarativeecmascript::eval()
3810 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3812 QObject *o = component.create();
3815 QCOMPARE(o->property("test1").toBool(), true);
3816 QCOMPARE(o->property("test2").toBool(), true);
3817 QCOMPARE(o->property("test3").toBool(), true);
3818 QCOMPARE(o->property("test4").toBool(), true);
3819 QCOMPARE(o->property("test5").toBool(), true);
3824 void tst_qdeclarativeecmascript::function()
3826 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3828 QObject *o = component.create();
3831 QCOMPARE(o->property("test1").toBool(), true);
3832 QCOMPARE(o->property("test2").toBool(), true);
3833 QCOMPARE(o->property("test3").toBool(), true);
3838 // Test the "Qt.include" method
3839 void tst_qdeclarativeecmascript::include()
3841 // Non-library relative include
3843 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3844 QObject *o = component.create();
3847 QCOMPARE(o->property("test0").toInt(), 99);
3848 QCOMPARE(o->property("test1").toBool(), true);
3849 QCOMPARE(o->property("test2").toBool(), true);
3850 QCOMPARE(o->property("test2_1").toBool(), true);
3851 QCOMPARE(o->property("test3").toBool(), true);
3852 QCOMPARE(o->property("test3_1").toBool(), true);
3857 // Library relative include
3859 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3860 QObject *o = component.create();
3863 QCOMPARE(o->property("test0").toInt(), 99);
3864 QCOMPARE(o->property("test1").toBool(), true);
3865 QCOMPARE(o->property("test2").toBool(), true);
3866 QCOMPARE(o->property("test2_1").toBool(), true);
3867 QCOMPARE(o->property("test3").toBool(), true);
3868 QCOMPARE(o->property("test3_1").toBool(), true);
3875 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3876 QObject *o = component.create();
3879 QCOMPARE(o->property("test1").toBool(), true);
3880 QCOMPARE(o->property("test2").toBool(), true);
3881 QCOMPARE(o->property("test3").toBool(), true);
3882 QCOMPARE(o->property("test4").toBool(), true);
3883 QCOMPARE(o->property("test5").toBool(), true);
3884 QCOMPARE(o->property("test6").toBool(), true);
3889 // Including file with ".pragma library"
3891 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3892 QObject *o = component.create();
3894 QCOMPARE(o->property("test1").toInt(), 100);
3901 TestHTTPServer server(8111);
3902 QVERIFY(server.isValid());
3903 server.serveDirectory(SRCDIR "/data");
3905 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3906 QObject *o = component.create();
3909 QTRY_VERIFY(o->property("done").toBool() == true);
3910 QTRY_VERIFY(o->property("done2").toBool() == true);
3912 QCOMPARE(o->property("test1").toBool(), true);
3913 QCOMPARE(o->property("test2").toBool(), true);
3914 QCOMPARE(o->property("test3").toBool(), true);
3915 QCOMPARE(o->property("test4").toBool(), true);
3916 QCOMPARE(o->property("test5").toBool(), true);
3918 QCOMPARE(o->property("test6").toBool(), true);
3919 QCOMPARE(o->property("test7").toBool(), true);
3920 QCOMPARE(o->property("test8").toBool(), true);
3921 QCOMPARE(o->property("test9").toBool(), true);
3922 QCOMPARE(o->property("test10").toBool(), true);
3929 TestHTTPServer server(8111);
3930 QVERIFY(server.isValid());
3931 server.serveDirectory(SRCDIR "/data");
3933 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3934 QObject *o = component.create();
3937 QTRY_VERIFY(o->property("done").toBool() == true);
3939 QCOMPARE(o->property("test1").toBool(), true);
3940 QCOMPARE(o->property("test2").toBool(), true);
3941 QCOMPARE(o->property("test3").toBool(), true);
3947 void tst_qdeclarativeecmascript::signalHandlers()
3949 QDeclarativeComponent component(&engine, TEST_FILE("signalHandlers.qml"));
3950 QObject *o = component.create();
3953 QVERIFY(o->property("count").toInt() == 0);
3954 QMetaObject::invokeMethod(o, "testSignalCall");
3955 QCOMPARE(o->property("count").toInt(), 1);
3957 QMetaObject::invokeMethod(o, "testSignalHandlerCall");
3958 QCOMPARE(o->property("count").toInt(), 1);
3959 QCOMPARE(o->property("errorString").toString(), QLatin1String("TypeError: Property 'onTestSignal' of object [object Object] is not a function"));
3961 QVERIFY(o->property("funcCount").toInt() == 0);
3962 QMetaObject::invokeMethod(o, "testSignalConnection");
3963 QCOMPARE(o->property("funcCount").toInt(), 1);
3965 QMetaObject::invokeMethod(o, "testSignalHandlerConnection");
3966 QCOMPARE(o->property("funcCount").toInt(), 2);
3968 QMetaObject::invokeMethod(o, "testSignalDefined");
3969 QCOMPARE(o->property("definedResult").toBool(), true);
3971 QMetaObject::invokeMethod(o, "testSignalHandlerDefined");
3972 QCOMPARE(o->property("definedHandlerResult").toBool(), true);
3977 void tst_qdeclarativeecmascript::qtbug_10696()
3979 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3980 QObject *o = component.create();
3985 void tst_qdeclarativeecmascript::qtbug_11606()
3987 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3988 QObject *o = component.create();
3990 QCOMPARE(o->property("test").toBool(), true);
3994 void tst_qdeclarativeecmascript::qtbug_11600()
3996 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3997 QObject *o = component.create();
3999 QCOMPARE(o->property("test").toBool(), true);
4003 // Reading and writing non-scriptable properties should fail
4004 void tst_qdeclarativeecmascript::nonscriptable()
4006 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
4007 QObject *o = component.create();
4009 QCOMPARE(o->property("readOk").toBool(), true);
4010 QCOMPARE(o->property("writeOk").toBool(), true);
4014 // deleteLater() should not be callable from QML
4015 void tst_qdeclarativeecmascript::deleteLater()
4017 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
4018 QObject *o = component.create();
4020 QCOMPARE(o->property("test").toBool(), true);
4024 void tst_qdeclarativeecmascript::in()
4026 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
4027 QObject *o = component.create();
4029 QCOMPARE(o->property("test1").toBool(), true);
4030 QCOMPARE(o->property("test2").toBool(), true);
4034 void tst_qdeclarativeecmascript::sharedAttachedObject()
4036 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
4037 QObject *o = component.create();
4039 QCOMPARE(o->property("test1").toBool(), true);
4040 QCOMPARE(o->property("test2").toBool(), true);
4045 void tst_qdeclarativeecmascript::objectName()
4047 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
4048 QObject *o = component.create();
4051 QCOMPARE(o->property("test1").toString(), QString("hello"));
4052 QCOMPARE(o->property("test2").toString(), QString("ell"));
4054 o->setObjectName("world");
4056 QCOMPARE(o->property("test1").toString(), QString("world"));
4057 QCOMPARE(o->property("test2").toString(), QString("orl"));
4062 void tst_qdeclarativeecmascript::writeRemovesBinding()
4064 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
4065 QObject *o = component.create();
4068 QCOMPARE(o->property("test").toBool(), true);
4073 // Test bindings assigned to alias properties actually assign to the alias' target
4074 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
4076 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
4077 QObject *o = component.create();
4080 QCOMPARE(o->property("test").toBool(), true);
4085 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
4086 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
4089 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
4090 QObject *o = component.create();
4093 QCOMPARE(o->property("test").toBool(), true);
4099 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
4100 QObject *o = component.create();
4103 QCOMPARE(o->property("test").toBool(), true);
4109 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
4110 QObject *o = component.create();
4113 QCOMPARE(o->property("test").toBool(), true);
4119 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
4120 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
4123 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
4124 QObject *o = component.create();
4127 QCOMPARE(o->property("test").toBool(), true);
4133 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
4134 QObject *o = component.create();
4137 QCOMPARE(o->property("test").toBool(), true);
4143 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
4144 QObject *o = component.create();
4147 QCOMPARE(o->property("test").toBool(), true);
4153 // Allow an alais to a composite element
4155 void tst_qdeclarativeecmascript::aliasToCompositeElement()
4157 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
4159 QObject *object = component.create();
4160 QVERIFY(object != 0);
4165 void tst_qdeclarativeecmascript::revisionErrors()
4168 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
4169 QString url = component.url().toString();
4171 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
4172 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
4173 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
4175 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
4176 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
4177 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
4178 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4179 QVERIFY(object != 0);
4183 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
4184 QString url = component.url().toString();
4186 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
4187 // method2, prop2 from MyRevisionedClass not available
4188 // method4, prop4 from MyRevisionedSubclass not available
4189 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
4190 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
4191 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
4192 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
4193 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
4195 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
4196 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
4197 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
4198 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
4199 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
4200 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4201 QVERIFY(object != 0);
4205 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
4206 QString url = component.url().toString();
4208 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
4209 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
4210 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
4211 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
4212 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
4213 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
4214 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
4215 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
4216 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4217 QVERIFY(object != 0);
4222 void tst_qdeclarativeecmascript::revision()
4225 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
4226 QString url = component.url().toString();
4228 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4229 QVERIFY(object != 0);
4233 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
4234 QString url = component.url().toString();
4236 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4237 QVERIFY(object != 0);
4241 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
4242 QString url = component.url().toString();
4244 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4245 QVERIFY(object != 0);
4248 // Test that non-root classes can resolve revisioned methods
4250 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
4252 QObject *object = component.create();
4253 QVERIFY(object != 0);
4254 QCOMPARE(object->property("test").toReal(), 11.);
4259 void tst_qdeclarativeecmascript::realToInt()
4261 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
4262 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
4263 QVERIFY(object != 0);
4265 QMetaObject::invokeMethod(object, "test1");
4266 QCOMPARE(object->value(), int(4));
4267 QMetaObject::invokeMethod(object, "test2");
4268 QCOMPARE(object->value(), int(8));
4270 void tst_qdeclarativeecmascript::dynamicString()
4272 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
4273 QObject *object = component.create();
4274 QVERIFY(object != 0);
4275 QCOMPARE(object->property("stringProperty").toString(),
4276 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
4279 void tst_qdeclarativeecmascript::automaticSemicolon()
4281 QDeclarativeComponent component(&engine, TEST_FILE("automaticSemicolon.qml"));
4282 QObject *object = component.create();
4283 QVERIFY(object != 0);
4286 QTEST_MAIN(tst_qdeclarativeecmascript)
4288 #include "tst_qdeclarativeecmascript.moc"