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();
166 void dynamicCreationCrash();
168 void nullObjectBinding();
169 void deletedEngine();
170 void libraryScriptAssert();
171 void variantsAssignedUndefined();
173 void qtcreatorbug_1289();
174 void noSpuriousWarningsAtShutdown();
175 void canAssignNullToQObject();
176 void functionAssignment_fromBinding();
177 void functionAssignment_fromJS();
178 void functionAssignment_fromJS_data();
179 void functionAssignmentfromJS_invalid();
185 void nonscriptable();
188 void sharedAttachedObject();
190 void writeRemovesBinding();
191 void aliasBindingsAssignCorrectly();
192 void aliasBindingsOverrideTarget();
193 void aliasWritesOverrideBindings();
194 void aliasToCompositeElement();
196 void dynamicString();
198 void signalHandlers();
200 void callQtInvokables();
201 void invokableObjectArg();
202 void invokableObjectRet();
204 void revisionErrors();
207 void automaticSemicolon();
210 QDeclarativeEngine engine;
213 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
215 void tst_qdeclarativeecmascript::assignBasicTypes()
218 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
219 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
220 QVERIFY(object != 0);
221 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
222 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
223 QCOMPARE(object->stringProperty(), QString("Hello World!"));
224 QCOMPARE(object->uintProperty(), uint(10));
225 QCOMPARE(object->intProperty(), -19);
226 QCOMPARE((float)object->realProperty(), float(23.2));
227 QCOMPARE((float)object->doubleProperty(), float(-19.75));
228 QCOMPARE((float)object->floatProperty(), float(8.5));
229 QCOMPARE(object->colorProperty(), QColor("red"));
230 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
231 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
232 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
233 QCOMPARE(object->pointProperty(), QPoint(99,13));
234 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
235 QCOMPARE(object->sizeProperty(), QSize(99, 13));
236 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
237 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
238 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
239 QCOMPARE(object->boolProperty(), true);
240 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
241 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
242 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
246 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
247 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
248 QVERIFY(object != 0);
249 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
250 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
251 QCOMPARE(object->stringProperty(), QString("Hello World!"));
252 QCOMPARE(object->uintProperty(), uint(10));
253 QCOMPARE(object->intProperty(), -19);
254 QCOMPARE((float)object->realProperty(), float(23.2));
255 QCOMPARE((float)object->doubleProperty(), float(-19.75));
256 QCOMPARE((float)object->floatProperty(), float(8.5));
257 QCOMPARE(object->colorProperty(), QColor("red"));
258 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
259 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
260 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
261 QCOMPARE(object->pointProperty(), QPoint(99,13));
262 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
263 QCOMPARE(object->sizeProperty(), QSize(99, 13));
264 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
265 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
266 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
267 QCOMPARE(object->boolProperty(), true);
268 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
269 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
270 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
275 void tst_qdeclarativeecmascript::idShortcutInvalidates()
278 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
279 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
280 QVERIFY(object != 0);
281 QVERIFY(object->objectProperty() != 0);
282 delete object->objectProperty();
283 QVERIFY(object->objectProperty() == 0);
288 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
289 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
290 QVERIFY(object != 0);
291 QVERIFY(object->objectProperty() != 0);
292 delete object->objectProperty();
293 QVERIFY(object->objectProperty() == 0);
298 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
301 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
302 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
303 QVERIFY(object != 0);
304 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
308 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
309 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
310 QVERIFY(object != 0);
311 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
316 void tst_qdeclarativeecmascript::signalAssignment()
319 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
320 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
321 QVERIFY(object != 0);
322 QCOMPARE(object->string(), QString());
323 emit object->basicSignal();
324 QCOMPARE(object->string(), QString("pass"));
329 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
330 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
331 QVERIFY(object != 0);
332 QCOMPARE(object->string(), QString());
333 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
334 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
339 void tst_qdeclarativeecmascript::methods()
342 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
343 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
344 QVERIFY(object != 0);
345 QCOMPARE(object->methodCalled(), false);
346 QCOMPARE(object->methodIntCalled(), false);
347 emit object->basicSignal();
348 QCOMPARE(object->methodCalled(), true);
349 QCOMPARE(object->methodIntCalled(), false);
354 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
355 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
356 QVERIFY(object != 0);
357 QCOMPARE(object->methodCalled(), false);
358 QCOMPARE(object->methodIntCalled(), false);
359 emit object->basicSignal();
360 QCOMPARE(object->methodCalled(), false);
361 QCOMPARE(object->methodIntCalled(), true);
366 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
367 QObject *object = component.create();
368 QVERIFY(object != 0);
369 QCOMPARE(object->property("test").toInt(), 19);
374 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
375 QObject *object = component.create();
376 QVERIFY(object != 0);
377 QCOMPARE(object->property("test").toInt(), 19);
378 QCOMPARE(object->property("test2").toInt(), 17);
379 QCOMPARE(object->property("test3").toInt(), 16);
384 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
385 QObject *object = component.create();
386 QVERIFY(object != 0);
387 QCOMPARE(object->property("test").toInt(), 9);
392 void tst_qdeclarativeecmascript::bindingLoop()
394 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
395 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
396 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
397 QObject *object = component.create();
398 QVERIFY(object != 0);
402 void tst_qdeclarativeecmascript::basicExpressions_data()
404 QTest::addColumn<QString>("expression");
405 QTest::addColumn<QVariant>("result");
406 QTest::addColumn<bool>("nest");
408 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
409 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
410 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
411 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
412 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
413 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
414 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
415 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
416 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
417 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
418 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
419 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
420 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
421 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
422 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
423 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
424 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
425 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
426 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
429 void tst_qdeclarativeecmascript::basicExpressions()
431 QFETCH(QString, expression);
432 QFETCH(QVariant, result);
438 MyDefaultObject1 default1;
439 MyDefaultObject3 default3;
440 object1.setStringProperty("Object1");
441 object2.setStringProperty("Object2");
442 object3.setStringProperty("Object3");
444 QDeclarativeContext context(engine.rootContext());
445 QDeclarativeContext nestedContext(&context);
447 context.setContextObject(&default1);
448 context.setContextProperty("a", QVariant(1944));
449 context.setContextProperty("b", QVariant("Milk"));
450 context.setContextProperty("object", &object1);
451 context.setContextProperty("objectOverride", &object2);
452 nestedContext.setContextObject(&default3);
453 nestedContext.setContextProperty("b", QVariant("Cow"));
454 nestedContext.setContextProperty("objectOverride", &object3);
455 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
457 MyExpression expr(nest?&nestedContext:&context, expression);
458 QCOMPARE(expr.evaluate(), result);
461 void tst_qdeclarativeecmascript::arrayExpressions()
467 QDeclarativeContext context(engine.rootContext());
468 context.setContextProperty("a", &obj1);
469 context.setContextProperty("b", &obj2);
470 context.setContextProperty("c", &obj3);
472 MyExpression expr(&context, "[a, b, c, 10]");
473 QVariant result = expr.evaluate();
474 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
475 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
476 QCOMPARE(list.count(), 4);
477 QCOMPARE(list.at(0), &obj1);
478 QCOMPARE(list.at(1), &obj2);
479 QCOMPARE(list.at(2), &obj3);
480 QCOMPARE(list.at(3), (QObject *)0);
483 // Tests that modifying a context property will reevaluate expressions
484 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
486 QDeclarativeContext context(engine.rootContext());
489 MyQmlObject *object3 = new MyQmlObject;
491 object1.setStringProperty("Hello");
492 object2.setStringProperty("World");
494 context.setContextProperty("testProp", QVariant(1));
495 context.setContextProperty("testObj", &object1);
496 context.setContextProperty("testObj2", object3);
499 MyExpression expr(&context, "testProp + 1");
500 QCOMPARE(expr.changed, false);
501 QCOMPARE(expr.evaluate(), QVariant(2));
503 context.setContextProperty("testProp", QVariant(2));
504 QCOMPARE(expr.changed, true);
505 QCOMPARE(expr.evaluate(), QVariant(3));
509 MyExpression expr(&context, "testProp + testProp + testProp");
510 QCOMPARE(expr.changed, false);
511 QCOMPARE(expr.evaluate(), QVariant(6));
513 context.setContextProperty("testProp", QVariant(4));
514 QCOMPARE(expr.changed, true);
515 QCOMPARE(expr.evaluate(), QVariant(12));
519 MyExpression expr(&context, "testObj.stringProperty");
520 QCOMPARE(expr.changed, false);
521 QCOMPARE(expr.evaluate(), QVariant("Hello"));
523 context.setContextProperty("testObj", &object2);
524 QCOMPARE(expr.changed, true);
525 QCOMPARE(expr.evaluate(), QVariant("World"));
529 MyExpression expr(&context, "testObj.stringProperty /**/");
530 QCOMPARE(expr.changed, false);
531 QCOMPARE(expr.evaluate(), QVariant("World"));
533 context.setContextProperty("testObj", &object1);
534 QCOMPARE(expr.changed, true);
535 QCOMPARE(expr.evaluate(), QVariant("Hello"));
539 MyExpression expr(&context, "testObj2");
540 QCOMPARE(expr.changed, false);
541 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
547 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
549 QDeclarativeContext context(engine.rootContext());
553 context.setContextProperty("testObj", &object1);
555 object1.setStringProperty(QLatin1String("Hello"));
556 object2.setStringProperty(QLatin1String("Dog"));
557 object3.setStringProperty(QLatin1String("Cat"));
560 MyExpression expr(&context, "testObj.stringProperty");
561 QCOMPARE(expr.changed, false);
562 QCOMPARE(expr.evaluate(), QVariant("Hello"));
564 object1.setStringProperty(QLatin1String("World"));
565 QCOMPARE(expr.changed, true);
566 QCOMPARE(expr.evaluate(), QVariant("World"));
570 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
571 QCOMPARE(expr.changed, false);
572 QCOMPARE(expr.evaluate(), QVariant());
574 object1.setObjectProperty(&object2);
575 QCOMPARE(expr.changed, true);
576 expr.changed = false;
577 QCOMPARE(expr.evaluate(), QVariant("Dog"));
579 object1.setObjectProperty(&object3);
580 QCOMPARE(expr.changed, true);
581 expr.changed = false;
582 QCOMPARE(expr.evaluate(), QVariant("Cat"));
584 object1.setObjectProperty(0);
585 QCOMPARE(expr.changed, true);
586 expr.changed = false;
587 QCOMPARE(expr.evaluate(), QVariant());
589 object1.setObjectProperty(&object3);
590 QCOMPARE(expr.changed, true);
591 expr.changed = false;
592 QCOMPARE(expr.evaluate(), QVariant("Cat"));
594 object3.setStringProperty("Donkey");
595 QCOMPARE(expr.changed, true);
596 expr.changed = false;
597 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
601 void tst_qdeclarativeecmascript::deferredProperties()
603 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
604 MyDeferredObject *object =
605 qobject_cast<MyDeferredObject *>(component.create());
606 QVERIFY(object != 0);
607 QCOMPARE(object->value(), 0);
608 QVERIFY(object->objectProperty() == 0);
609 QVERIFY(object->objectProperty2() != 0);
610 qmlExecuteDeferred(object);
611 QCOMPARE(object->value(), 10);
612 QVERIFY(object->objectProperty() != 0);
613 MyQmlObject *qmlObject =
614 qobject_cast<MyQmlObject *>(object->objectProperty());
615 QVERIFY(qmlObject != 0);
616 QCOMPARE(qmlObject->value(), 10);
617 object->setValue(19);
618 QCOMPARE(qmlObject->value(), 19);
623 // Check errors on deferred properties are correctly emitted
624 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
626 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
627 MyDeferredObject *object =
628 qobject_cast<MyDeferredObject *>(component.create());
629 QVERIFY(object != 0);
630 QCOMPARE(object->value(), 0);
631 QVERIFY(object->objectProperty() == 0);
632 QVERIFY(object->objectProperty2() == 0);
634 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
635 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
637 qmlExecuteDeferred(object);
642 void tst_qdeclarativeecmascript::extensionObjects()
644 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
645 MyExtendedObject *object =
646 qobject_cast<MyExtendedObject *>(component.create());
647 QVERIFY(object != 0);
648 QCOMPARE(object->baseProperty(), 13);
649 QCOMPARE(object->coreProperty(), 9);
650 object->setProperty("extendedProperty", QVariant(11));
651 object->setProperty("baseExtendedProperty", QVariant(92));
652 QCOMPARE(object->coreProperty(), 11);
653 QCOMPARE(object->baseProperty(), 92);
655 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
657 QCOMPARE(nested->baseProperty(), 13);
658 QCOMPARE(nested->coreProperty(), 9);
659 nested->setProperty("extendedProperty", QVariant(11));
660 nested->setProperty("baseExtendedProperty", QVariant(92));
661 QCOMPARE(nested->coreProperty(), 11);
662 QCOMPARE(nested->baseProperty(), 92);
667 void tst_qdeclarativeecmascript::overrideExtensionProperties()
669 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
670 OverrideDefaultPropertyObject *object =
671 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
672 QVERIFY(object != 0);
673 QVERIFY(object->secondProperty() != 0);
674 QVERIFY(object->firstProperty() == 0);
679 void tst_qdeclarativeecmascript::attachedProperties()
682 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
683 QObject *object = component.create();
684 QVERIFY(object != 0);
685 QCOMPARE(object->property("a").toInt(), 19);
686 QCOMPARE(object->property("b").toInt(), 19);
687 QCOMPARE(object->property("c").toInt(), 19);
688 QCOMPARE(object->property("d").toInt(), 19);
693 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
694 QObject *object = component.create();
695 QVERIFY(object != 0);
696 QCOMPARE(object->property("a").toInt(), 26);
697 QCOMPARE(object->property("b").toInt(), 26);
698 QCOMPARE(object->property("c").toInt(), 26);
699 QCOMPARE(object->property("d").toInt(), 26);
705 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
706 QObject *object = component.create();
707 QVERIFY(object != 0);
709 QMetaObject::invokeMethod(object, "writeValue2");
711 MyQmlAttachedObject *attached =
712 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
713 QVERIFY(attached != 0);
715 QCOMPARE(attached->value2(), 9);
720 void tst_qdeclarativeecmascript::enums()
724 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
725 QObject *object = component.create();
726 QVERIFY(object != 0);
728 QCOMPARE(object->property("a").toInt(), 0);
729 QCOMPARE(object->property("b").toInt(), 1);
730 QCOMPARE(object->property("c").toInt(), 2);
731 QCOMPARE(object->property("d").toInt(), 3);
732 QCOMPARE(object->property("e").toInt(), 0);
733 QCOMPARE(object->property("f").toInt(), 1);
734 QCOMPARE(object->property("g").toInt(), 2);
735 QCOMPARE(object->property("h").toInt(), 3);
736 QCOMPARE(object->property("i").toInt(), 19);
737 QCOMPARE(object->property("j").toInt(), 19);
741 // Non-existent enums
743 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
745 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
746 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
747 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
748 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
750 QObject *object = component.create();
751 QVERIFY(object != 0);
752 QCOMPARE(object->property("a").toInt(), 0);
753 QCOMPARE(object->property("b").toInt(), 0);
759 void tst_qdeclarativeecmascript::valueTypeFunctions()
761 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
762 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
764 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
765 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
771 Tests that writing a constant to a property with a binding on it disables the
774 void tst_qdeclarativeecmascript::constantsOverrideBindings()
778 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
779 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
780 QVERIFY(object != 0);
782 QCOMPARE(object->property("c2").toInt(), 0);
783 object->setProperty("c1", QVariant(9));
784 QCOMPARE(object->property("c2").toInt(), 9);
786 emit object->basicSignal();
788 QCOMPARE(object->property("c2").toInt(), 13);
789 object->setProperty("c1", QVariant(8));
790 QCOMPARE(object->property("c2").toInt(), 13);
795 // During construction
797 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
798 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
799 QVERIFY(object != 0);
801 QCOMPARE(object->property("c1").toInt(), 0);
802 QCOMPARE(object->property("c2").toInt(), 10);
803 object->setProperty("c1", QVariant(9));
804 QCOMPARE(object->property("c1").toInt(), 9);
805 QCOMPARE(object->property("c2").toInt(), 10);
813 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
814 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
815 QVERIFY(object != 0);
817 QCOMPARE(object->property("c2").toInt(), 0);
818 object->setProperty("c1", QVariant(9));
819 QCOMPARE(object->property("c2").toInt(), 9);
821 object->setProperty("c2", QVariant(13));
822 QCOMPARE(object->property("c2").toInt(), 13);
823 object->setProperty("c1", QVariant(7));
824 QCOMPARE(object->property("c1").toInt(), 7);
825 QCOMPARE(object->property("c2").toInt(), 13);
833 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
834 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
835 QVERIFY(object != 0);
837 QCOMPARE(object->property("c1").toInt(), 0);
838 QCOMPARE(object->property("c3").toInt(), 10);
839 object->setProperty("c1", QVariant(9));
840 QCOMPARE(object->property("c1").toInt(), 9);
841 QCOMPARE(object->property("c3").toInt(), 10);
848 Tests that assigning a binding to a property that already has a binding causes
849 the original binding to be disabled.
851 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
853 QDeclarativeComponent component(&engine,
854 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
855 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
856 QVERIFY(object != 0);
858 QCOMPARE(object->property("c1").toInt(), 0);
859 QCOMPARE(object->property("c2").toInt(), 0);
860 QCOMPARE(object->property("c3").toInt(), 0);
862 object->setProperty("c1", QVariant(9));
863 QCOMPARE(object->property("c1").toInt(), 9);
864 QCOMPARE(object->property("c2").toInt(), 0);
865 QCOMPARE(object->property("c3").toInt(), 0);
867 object->setProperty("c3", QVariant(8));
868 QCOMPARE(object->property("c1").toInt(), 9);
869 QCOMPARE(object->property("c2").toInt(), 8);
870 QCOMPARE(object->property("c3").toInt(), 8);
876 Access a non-existent attached object.
878 Tests for a regression where this used to crash.
880 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
882 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
884 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
885 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
887 QObject *object = component.create();
888 QVERIFY(object != 0);
893 void tst_qdeclarativeecmascript::scope()
896 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
897 QObject *object = component.create();
898 QVERIFY(object != 0);
900 QCOMPARE(object->property("test1").toInt(), 1);
901 QCOMPARE(object->property("test2").toInt(), 2);
902 QCOMPARE(object->property("test3").toString(), QString("1Test"));
903 QCOMPARE(object->property("test4").toString(), QString("2Test"));
904 QCOMPARE(object->property("test5").toInt(), 1);
905 QCOMPARE(object->property("test6").toInt(), 1);
906 QCOMPARE(object->property("test7").toInt(), 2);
907 QCOMPARE(object->property("test8").toInt(), 2);
908 QCOMPARE(object->property("test9").toInt(), 1);
909 QCOMPARE(object->property("test10").toInt(), 3);
915 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
916 QObject *object = component.create();
917 QVERIFY(object != 0);
919 QCOMPARE(object->property("test1").toInt(), 19);
920 QCOMPARE(object->property("test2").toInt(), 19);
921 QCOMPARE(object->property("test3").toInt(), 14);
922 QCOMPARE(object->property("test4").toInt(), 14);
923 QCOMPARE(object->property("test5").toInt(), 24);
924 QCOMPARE(object->property("test6").toInt(), 24);
930 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
931 QObject *object = component.create();
932 QVERIFY(object != 0);
934 QCOMPARE(object->property("test1").toBool(), true);
935 QCOMPARE(object->property("test2").toBool(), true);
936 QCOMPARE(object->property("test3").toBool(), true);
941 // Signal argument scope
943 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
944 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
945 QVERIFY(object != 0);
947 QCOMPARE(object->property("test").toInt(), 0);
948 QCOMPARE(object->property("test2").toString(), QString());
950 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
952 QCOMPARE(object->property("test").toInt(), 13);
953 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
959 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
960 QObject *object = component.create();
961 QVERIFY(object != 0);
963 QCOMPARE(object->property("test1").toBool(), true);
964 QCOMPARE(object->property("test2").toBool(), true);
970 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
971 QObject *object = component.create();
972 QVERIFY(object != 0);
974 QCOMPARE(object->property("test").toBool(), true);
980 // In 4.7, non-library javascript files that had no imports shared the imports of their
982 void tst_qdeclarativeecmascript::importScope()
984 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
985 QObject *o = component.create();
988 QCOMPARE(o->property("test").toInt(), 240);
994 Tests that "any" type passes through a synthesized signal parameter. This
995 is essentially a test of QDeclarativeMetaType::copy()
997 void tst_qdeclarativeecmascript::signalParameterTypes()
999 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
1000 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1001 QVERIFY(object != 0);
1003 emit object->basicSignal();
1005 QCOMPARE(object->property("intProperty").toInt(), 10);
1006 QCOMPARE(object->property("realProperty").toReal(), 19.2);
1007 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
1008 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
1009 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
1010 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
1016 Test that two JS objects for the same QObject compare as equal.
1018 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1020 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1021 QObject *object = component.create();
1022 QVERIFY(object != 0);
1024 QCOMPARE(object->property("test1").toBool(), true);
1025 QCOMPARE(object->property("test2").toBool(), true);
1026 QCOMPARE(object->property("test3").toBool(), true);
1027 QCOMPARE(object->property("test4").toBool(), true);
1028 QCOMPARE(object->property("test5").toBool(), true);
1034 Confirm bindings and alias properties can coexist.
1036 Tests for a regression where the binding would not reevaluate.
1038 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1040 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1041 QObject *object = component.create();
1042 QVERIFY(object != 0);
1044 QCOMPARE(object->property("c2").toInt(), 3);
1045 QCOMPARE(object->property("c3").toInt(), 3);
1047 object->setProperty("c2", QVariant(19));
1049 QCOMPARE(object->property("c2").toInt(), 19);
1050 QCOMPARE(object->property("c3").toInt(), 19);
1056 Ensure that we can write undefined value to an alias property,
1057 and that the aliased property is reset correctly if possible.
1059 void tst_qdeclarativeecmascript::aliasPropertyReset()
1061 QObject *object = 0;
1063 // test that a manual write (of undefined) to a resettable aliased property succeeds
1064 QDeclarativeComponent c1(&engine, TEST_FILE("aliasreset/aliasPropertyReset.1.qml"));
1065 object = c1.create();
1066 QVERIFY(object != 0);
1067 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1068 QCOMPARE(object->property("aliasIsUndefined"), QVariant(false));
1069 QMetaObject::invokeMethod(object, "resetAliased");
1070 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1071 QCOMPARE(object->property("aliasIsUndefined"), QVariant(true));
1074 // test that a manual write (of undefined) to a resettable alias property succeeds
1075 QDeclarativeComponent c2(&engine, TEST_FILE("aliasreset/aliasPropertyReset.2.qml"));
1076 object = c2.create();
1077 QVERIFY(object != 0);
1078 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1079 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(false));
1080 QMetaObject::invokeMethod(object, "resetAlias");
1081 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1082 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(true));
1085 // test that an alias to a bound property works correctly
1086 QDeclarativeComponent c3(&engine, TEST_FILE("aliasreset/aliasPropertyReset.3.qml"));
1087 object = c3.create();
1088 QVERIFY(object != 0);
1089 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1090 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(false));
1091 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1092 QMetaObject::invokeMethod(object, "resetAlias");
1093 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1094 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(true));
1095 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1098 // test that a manual write (of undefined) to a resettable alias property
1099 // whose aliased property's object has been deleted, does not crash.
1100 QDeclarativeComponent c4(&engine, TEST_FILE("aliasreset/aliasPropertyReset.4.qml"));
1101 object = c4.create();
1102 QVERIFY(object != 0);
1103 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1104 QObject *loader = object->findChild<QObject*>("loader");
1105 QVERIFY(loader != 0);
1107 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // deletion should have caused value unset.
1108 QMetaObject::invokeMethod(object, "resetAlias"); // shouldn't crash.
1109 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1110 QMetaObject::invokeMethod(object, "setAlias"); // shouldn't crash, and shouldn't change value (since it's no longer referencing anything).
1111 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1114 // test that binding an alias property to an undefined value works correctly
1115 QDeclarativeComponent c5(&engine, TEST_FILE("aliasreset/aliasPropertyReset.5.qml"));
1116 object = c5.create();
1117 QVERIFY(object != 0);
1118 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // bound to undefined value.
1121 // test that a manual write (of undefined) to a non-resettable property fails properly
1122 QUrl url = TEST_FILE("aliasreset/aliasPropertyReset.error.1.qml");
1123 QString warning1 = url.toString() + QLatin1String(":15: Error: Cannot assign [undefined] to int");
1124 QDeclarativeComponent e1(&engine, url);
1125 object = e1.create();
1126 QVERIFY(object != 0);
1127 QCOMPARE(object->property("intAlias").value<int>(), 12);
1128 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1129 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1130 QMetaObject::invokeMethod(object, "resetAlias");
1131 QCOMPARE(object->property("intAlias").value<int>(), 12);
1132 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1136 void tst_qdeclarativeecmascript::dynamicCreation_data()
1138 QTest::addColumn<QString>("method");
1139 QTest::addColumn<QString>("createdName");
1141 QTest::newRow("One") << "createOne" << "objectOne";
1142 QTest::newRow("Two") << "createTwo" << "objectTwo";
1143 QTest::newRow("Three") << "createThree" << "objectThree";
1147 Test using createQmlObject to dynamically generate an item
1148 Also using createComponent is tested.
1150 void tst_qdeclarativeecmascript::dynamicCreation()
1152 QFETCH(QString, method);
1153 QFETCH(QString, createdName);
1155 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1156 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1157 QVERIFY(object != 0);
1159 QMetaObject::invokeMethod(object, method.toUtf8());
1160 QObject *created = object->objectProperty();
1162 QCOMPARE(created->objectName(), createdName);
1168 Tests the destroy function
1170 void tst_qdeclarativeecmascript::dynamicDestruction()
1173 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1174 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1175 QVERIFY(object != 0);
1176 QDeclarativeGuard<QObject> createdQmlObject = 0;
1178 QMetaObject::invokeMethod(object, "create");
1179 createdQmlObject = object->objectProperty();
1180 QVERIFY(createdQmlObject);
1181 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1183 QMetaObject::invokeMethod(object, "killOther");
1184 QVERIFY(createdQmlObject);
1185 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1186 QVERIFY(createdQmlObject);
1187 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1188 if (createdQmlObject) {
1190 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1193 QVERIFY(!createdQmlObject);
1195 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1196 QMetaObject::invokeMethod(object, "killMe");
1199 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1204 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.2.qml"));
1205 QObject *o = component.create();
1208 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1210 QMetaObject::invokeMethod(o, "create");
1212 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
1214 QMetaObject::invokeMethod(o, "destroy");
1216 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1218 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1225 tests that id.toString() works
1227 void tst_qdeclarativeecmascript::objectToString()
1229 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1230 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1231 QVERIFY(object != 0);
1232 QMetaObject::invokeMethod(object, "testToString");
1233 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1234 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1240 tests that id.hasOwnProperty() works
1242 void tst_qdeclarativeecmascript::objectHasOwnProperty()
1244 QUrl url = TEST_FILE("declarativeHasOwnProperty.qml");
1245 QString warning1 = url.toString() + ":59: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1246 QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1247 QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1249 QDeclarativeComponent component(&engine, url);
1250 QObject *object = component.create();
1251 QVERIFY(object != 0);
1253 // test QObjects in QML
1254 QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
1255 QVERIFY(object->property("result").value<bool>() == true);
1256 QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
1257 QVERIFY(object->property("result").value<bool>() == false);
1259 // now test other types in QML
1260 QObject *child = object->findChild<QObject*>("typeObj");
1261 QVERIFY(child != 0);
1262 QMetaObject::invokeMethod(child, "testHasOwnPropertySuccess");
1263 QCOMPARE(child->property("valueTypeHasOwnProperty").toBool(), true);
1264 QCOMPARE(child->property("valueTypeHasOwnProperty2").toBool(), true);
1265 QCOMPARE(child->property("variantTypeHasOwnProperty").toBool(), true);
1266 QCOMPARE(child->property("stringTypeHasOwnProperty").toBool(), true);
1267 QCOMPARE(child->property("listTypeHasOwnProperty").toBool(), true);
1268 QCOMPARE(child->property("emptyListTypeHasOwnProperty").toBool(), true);
1269 QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
1270 QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
1271 QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
1272 QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
1273 QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
1275 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1276 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
1277 QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
1278 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1279 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
1280 QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
1281 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1282 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
1283 QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
1289 Tests bindings that indirectly cause their own deletion work.
1291 This test is best run under valgrind to ensure no invalid memory access occur.
1293 void tst_qdeclarativeecmascript::selfDeletingBinding()
1296 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1297 QObject *object = component.create();
1298 QVERIFY(object != 0);
1299 object->setProperty("triggerDelete", true);
1304 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1305 QObject *object = component.create();
1306 QVERIFY(object != 0);
1307 object->setProperty("triggerDelete", true);
1313 Test that extended object properties can be accessed.
1315 This test a regression where this used to crash. The issue was specificially
1316 for extended objects that did not include a synthesized meta object (so non-root
1317 and no synthesiszed properties).
1319 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1321 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1322 QObject *object = component.create();
1323 QVERIFY(object != 0);
1328 Test file/lineNumbers for binding/Script errors.
1330 void tst_qdeclarativeecmascript::scriptErrors()
1332 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1333 QString url = component.url().toString();
1335 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1336 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1337 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1338 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1339 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1340 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1341 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1342 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1344 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1345 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1346 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1347 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1348 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1349 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1350 QVERIFY(object != 0);
1352 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1353 emit object->basicSignal();
1355 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1356 emit object->anotherBasicSignal();
1358 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1359 emit object->thirdBasicSignal();
1365 Test file/lineNumbers for inline functions.
1367 void tst_qdeclarativeecmascript::functionErrors()
1369 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1370 QString url = component.url().toString();
1372 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1374 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1376 QObject *object = component.create();
1377 QVERIFY(object != 0);
1380 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1381 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1382 url = componentTwo.url().toString();
1383 object = componentTwo.create();
1384 QVERIFY(object != 0);
1386 QString srpname = object->property("srp_name").toString();
1388 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1389 QLatin1String(" is not a function");
1390 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1391 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1396 Test various errors that can occur when assigning a property from script
1398 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1400 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1402 QString url = component.url().toString();
1404 QObject *object = component.create();
1405 QVERIFY(object != 0);
1407 QCOMPARE(object->property("test1").toBool(), true);
1408 QCOMPARE(object->property("test2").toBool(), true);
1414 Test bindings still work when the reeval is triggered from within
1417 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1419 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1420 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1421 QVERIFY(object != 0);
1423 QCOMPARE(object->property("base").toReal(), 50.);
1424 QCOMPARE(object->property("test1").toReal(), 50.);
1425 QCOMPARE(object->property("test2").toReal(), 50.);
1427 object->basicSignal();
1429 QCOMPARE(object->property("base").toReal(), 200.);
1430 QCOMPARE(object->property("test1").toReal(), 200.);
1431 QCOMPARE(object->property("test2").toReal(), 200.);
1433 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1435 QCOMPARE(object->property("base").toReal(), 400.);
1436 QCOMPARE(object->property("test1").toReal(), 400.);
1437 QCOMPARE(object->property("test2").toReal(), 400.);
1443 Test that list properties can be iterated from ECMAScript
1445 void tst_qdeclarativeecmascript::listProperties()
1447 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1448 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1449 QVERIFY(object != 0);
1451 QCOMPARE(object->property("test1").toInt(), 21);
1452 QCOMPARE(object->property("test2").toInt(), 2);
1453 QCOMPARE(object->property("test3").toBool(), true);
1454 QCOMPARE(object->property("test4").toBool(), true);
1459 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1461 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1462 QString url = component.url().toString();
1464 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1466 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1467 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1468 QVERIFY(object != 0);
1470 QCOMPARE(object->property("test").toBool(), false);
1472 MyQmlObject object2;
1473 MyQmlObject object3;
1474 object2.setObjectProperty(&object3);
1475 object->setObjectProperty(&object2);
1477 QCOMPARE(object->property("test").toBool(), true);
1482 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1484 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1485 QString url = component.url().toString();
1487 QString warning = component.url().toString() + ":6: Error: JS exception";
1489 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1490 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1491 QVERIFY(object != 0);
1495 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1497 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1498 QString url = component.url().toString();
1500 QString warning = component.url().toString() + ":5: Error: JS exception";
1502 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1503 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1504 QVERIFY(object != 0);
1508 static int transientErrorsMsgCount = 0;
1509 static void transientErrorsMsgHandler(QtMsgType, const char *)
1511 ++transientErrorsMsgCount;
1514 // Check that transient binding errors are not displayed
1515 void tst_qdeclarativeecmascript::transientErrors()
1518 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1520 transientErrorsMsgCount = 0;
1521 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1523 QObject *object = component.create();
1524 QVERIFY(object != 0);
1526 qInstallMsgHandler(old);
1528 QCOMPARE(transientErrorsMsgCount, 0);
1533 // One binding erroring multiple times, but then resolving
1535 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1537 transientErrorsMsgCount = 0;
1538 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1540 QObject *object = component.create();
1541 QVERIFY(object != 0);
1543 qInstallMsgHandler(old);
1545 QCOMPARE(transientErrorsMsgCount, 0);
1551 // Check that errors during shutdown are minimized
1552 void tst_qdeclarativeecmascript::shutdownErrors()
1554 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1555 QObject *object = component.create();
1556 QVERIFY(object != 0);
1558 transientErrorsMsgCount = 0;
1559 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1563 qInstallMsgHandler(old);
1564 QCOMPARE(transientErrorsMsgCount, 0);
1567 void tst_qdeclarativeecmascript::compositePropertyType()
1569 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1570 QTest::ignoreMessage(QtDebugMsg, "hello world");
1571 QObject *object = qobject_cast<QObject *>(component.create());
1576 void tst_qdeclarativeecmascript::jsObject()
1578 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1579 QObject *object = component.create();
1580 QVERIFY(object != 0);
1582 QCOMPARE(object->property("test").toInt(), 92);
1587 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1590 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1591 QObject *object = component.create();
1592 QVERIFY(object != 0);
1594 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1596 object->setProperty("setUndefined", true);
1598 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1600 object->setProperty("setUndefined", false);
1602 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1607 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1608 QObject *object = component.create();
1609 QVERIFY(object != 0);
1611 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1613 QMetaObject::invokeMethod(object, "doReset");
1615 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1622 void tst_qdeclarativeecmascript::bug1()
1624 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1625 QObject *object = component.create();
1626 QVERIFY(object != 0);
1628 QCOMPARE(object->property("test").toInt(), 14);
1630 object->setProperty("a", 11);
1632 QCOMPARE(object->property("test").toInt(), 3);
1634 object->setProperty("b", true);
1636 QCOMPARE(object->property("test").toInt(), 9);
1641 void tst_qdeclarativeecmascript::bug2()
1643 QDeclarativeComponent component(&engine);
1644 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1646 QObject *object = component.create();
1647 QVERIFY(object != 0);
1652 // Don't crash in createObject when the component has errors.
1653 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1655 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1656 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1657 QVERIFY(object != 0);
1659 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1660 QMetaObject::invokeMethod(object, "dontCrash");
1661 QObject *created = object->objectProperty();
1662 QVERIFY(created == 0);
1668 void tst_qdeclarativeecmascript::regExpBug()
1670 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1671 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1672 QVERIFY(object != 0);
1673 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1677 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1679 QString functionSource = QLatin1String("(function(object) { return ") +
1680 QLatin1String(source) + QLatin1String(" })");
1682 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1685 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1686 if (function.IsEmpty())
1688 v8::Handle<v8::Value> args[] = { o };
1689 function->Call(engine->global(), 1, args);
1690 return tc.HasCaught();
1693 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1694 const char *source, v8::Handle<v8::Value> result)
1696 QString functionSource = QLatin1String("(function(object) { return ") +
1697 QLatin1String(source) + QLatin1String(" })");
1699 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1702 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1703 if (function.IsEmpty())
1705 v8::Handle<v8::Value> args[] = { o };
1707 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1712 return value->StrictEquals(result);
1715 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1718 QString functionSource = QLatin1String("(function(object) { return ") +
1719 QLatin1String(source) + QLatin1String(" })");
1721 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1723 return v8::Handle<v8::Value>();
1724 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1725 if (function.IsEmpty())
1726 return v8::Handle<v8::Value>();
1727 v8::Handle<v8::Value> args[] = { o };
1729 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1732 return v8::Handle<v8::Value>();
1736 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1737 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1738 #define EVALUATE(source) evaluate(engine, object, source)
1740 void tst_qdeclarativeecmascript::callQtInvokables()
1742 MyInvokableObject o;
1744 QDeclarativeEngine qmlengine;
1745 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1747 QV8Engine *engine = ep->v8engine();
1749 v8::HandleScope handle_scope;
1750 v8::Context::Scope scope(engine->context());
1752 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1754 // Non-existent methods
1756 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1757 QCOMPARE(o.error(), false);
1758 QCOMPARE(o.invoked(), -1);
1759 QCOMPARE(o.actuals().count(), 0);
1762 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1763 QCOMPARE(o.error(), false);
1764 QCOMPARE(o.invoked(), -1);
1765 QCOMPARE(o.actuals().count(), 0);
1767 // Insufficient arguments
1769 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1770 QCOMPARE(o.error(), false);
1771 QCOMPARE(o.invoked(), -1);
1772 QCOMPARE(o.actuals().count(), 0);
1775 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1776 QCOMPARE(o.error(), false);
1777 QCOMPARE(o.invoked(), -1);
1778 QCOMPARE(o.actuals().count(), 0);
1780 // Excessive arguments
1782 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1783 QCOMPARE(o.error(), false);
1784 QCOMPARE(o.invoked(), 8);
1785 QCOMPARE(o.actuals().count(), 1);
1786 QCOMPARE(o.actuals().at(0), QVariant(10));
1789 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1790 QCOMPARE(o.error(), false);
1791 QCOMPARE(o.invoked(), 9);
1792 QCOMPARE(o.actuals().count(), 2);
1793 QCOMPARE(o.actuals().at(0), QVariant(10));
1794 QCOMPARE(o.actuals().at(1), QVariant(11));
1796 // Test return types
1798 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1799 QCOMPARE(o.error(), false);
1800 QCOMPARE(o.invoked(), 0);
1801 QCOMPARE(o.actuals().count(), 0);
1804 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1805 QCOMPARE(o.error(), false);
1806 QCOMPARE(o.invoked(), 1);
1807 QCOMPARE(o.actuals().count(), 0);
1810 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1811 QCOMPARE(o.error(), false);
1812 QCOMPARE(o.invoked(), 2);
1813 QCOMPARE(o.actuals().count(), 0);
1817 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1818 QVERIFY(!ret.IsEmpty());
1819 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1820 QCOMPARE(o.error(), false);
1821 QCOMPARE(o.invoked(), 3);
1822 QCOMPARE(o.actuals().count(), 0);
1827 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1828 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1829 QCOMPARE(o.error(), false);
1830 QCOMPARE(o.invoked(), 4);
1831 QCOMPARE(o.actuals().count(), 0);
1835 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1836 QCOMPARE(o.error(), false);
1837 QCOMPARE(o.invoked(), 5);
1838 QCOMPARE(o.actuals().count(), 0);
1842 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1843 QVERIFY(ret->IsString());
1844 QCOMPARE(engine->toString(ret), QString("Hello world"));
1845 QCOMPARE(o.error(), false);
1846 QCOMPARE(o.invoked(), 6);
1847 QCOMPARE(o.actuals().count(), 0);
1851 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1852 QCOMPARE(o.error(), false);
1853 QCOMPARE(o.invoked(), 7);
1854 QCOMPARE(o.actuals().count(), 0);
1858 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1859 QCOMPARE(o.error(), false);
1860 QCOMPARE(o.invoked(), 8);
1861 QCOMPARE(o.actuals().count(), 1);
1862 QCOMPARE(o.actuals().at(0), QVariant(94));
1865 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1866 QCOMPARE(o.error(), false);
1867 QCOMPARE(o.invoked(), 8);
1868 QCOMPARE(o.actuals().count(), 1);
1869 QCOMPARE(o.actuals().at(0), QVariant(94));
1872 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1873 QCOMPARE(o.error(), false);
1874 QCOMPARE(o.invoked(), 8);
1875 QCOMPARE(o.actuals().count(), 1);
1876 QCOMPARE(o.actuals().at(0), QVariant(0));
1879 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1880 QCOMPARE(o.error(), false);
1881 QCOMPARE(o.invoked(), 8);
1882 QCOMPARE(o.actuals().count(), 1);
1883 QCOMPARE(o.actuals().at(0), QVariant(0));
1886 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1887 QCOMPARE(o.error(), false);
1888 QCOMPARE(o.invoked(), 8);
1889 QCOMPARE(o.actuals().count(), 1);
1890 QCOMPARE(o.actuals().at(0), QVariant(0));
1893 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1894 QCOMPARE(o.error(), false);
1895 QCOMPARE(o.invoked(), 8);
1896 QCOMPARE(o.actuals().count(), 1);
1897 QCOMPARE(o.actuals().at(0), QVariant(0));
1900 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1901 QCOMPARE(o.error(), false);
1902 QCOMPARE(o.invoked(), 9);
1903 QCOMPARE(o.actuals().count(), 2);
1904 QCOMPARE(o.actuals().at(0), QVariant(122));
1905 QCOMPARE(o.actuals().at(1), QVariant(9));
1908 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1909 QCOMPARE(o.error(), false);
1910 QCOMPARE(o.invoked(), 10);
1911 QCOMPARE(o.actuals().count(), 1);
1912 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1915 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1916 QCOMPARE(o.error(), false);
1917 QCOMPARE(o.invoked(), 10);
1918 QCOMPARE(o.actuals().count(), 1);
1919 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1922 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1923 QCOMPARE(o.error(), false);
1924 QCOMPARE(o.invoked(), 10);
1925 QCOMPARE(o.actuals().count(), 1);
1926 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1929 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1930 QCOMPARE(o.error(), false);
1931 QCOMPARE(o.invoked(), 10);
1932 QCOMPARE(o.actuals().count(), 1);
1933 QCOMPARE(o.actuals().at(0), QVariant(0));
1936 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1937 QCOMPARE(o.error(), false);
1938 QCOMPARE(o.invoked(), 10);
1939 QCOMPARE(o.actuals().count(), 1);
1940 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1943 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1944 QCOMPARE(o.error(), false);
1945 QCOMPARE(o.invoked(), 10);
1946 QCOMPARE(o.actuals().count(), 1);
1947 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1950 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1951 QCOMPARE(o.error(), false);
1952 QCOMPARE(o.invoked(), 11);
1953 QCOMPARE(o.actuals().count(), 1);
1954 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1957 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1958 QCOMPARE(o.error(), false);
1959 QCOMPARE(o.invoked(), 11);
1960 QCOMPARE(o.actuals().count(), 1);
1961 QCOMPARE(o.actuals().at(0), QVariant("19"));
1965 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1966 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1967 QCOMPARE(o.error(), false);
1968 QCOMPARE(o.invoked(), 11);
1969 QCOMPARE(o.actuals().count(), 1);
1970 QCOMPARE(o.actuals().at(0), QVariant(expected));
1974 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1975 QCOMPARE(o.error(), false);
1976 QCOMPARE(o.invoked(), 11);
1977 QCOMPARE(o.actuals().count(), 1);
1978 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1981 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1982 QCOMPARE(o.error(), false);
1983 QCOMPARE(o.invoked(), 11);
1984 QCOMPARE(o.actuals().count(), 1);
1985 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1988 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1989 QCOMPARE(o.error(), false);
1990 QCOMPARE(o.invoked(), 12);
1991 QCOMPARE(o.actuals().count(), 1);
1992 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1995 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1996 QCOMPARE(o.error(), false);
1997 QCOMPARE(o.invoked(), 12);
1998 QCOMPARE(o.actuals().count(), 1);
1999 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2002 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
2003 QCOMPARE(o.error(), false);
2004 QCOMPARE(o.invoked(), 12);
2005 QCOMPARE(o.actuals().count(), 1);
2006 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2009 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
2010 QCOMPARE(o.error(), false);
2011 QCOMPARE(o.invoked(), 12);
2012 QCOMPARE(o.actuals().count(), 1);
2013 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2016 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
2017 QCOMPARE(o.error(), false);
2018 QCOMPARE(o.invoked(), 12);
2019 QCOMPARE(o.actuals().count(), 1);
2020 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
2023 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
2024 QCOMPARE(o.error(), false);
2025 QCOMPARE(o.invoked(), 12);
2026 QCOMPARE(o.actuals().count(), 1);
2027 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
2030 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
2031 QCOMPARE(o.error(), false);
2032 QCOMPARE(o.invoked(), 13);
2033 QCOMPARE(o.actuals().count(), 1);
2034 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2037 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
2038 QCOMPARE(o.error(), false);
2039 QCOMPARE(o.invoked(), 13);
2040 QCOMPARE(o.actuals().count(), 1);
2041 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2044 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
2045 QCOMPARE(o.error(), false);
2046 QCOMPARE(o.invoked(), 13);
2047 QCOMPARE(o.actuals().count(), 1);
2048 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2051 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
2052 QCOMPARE(o.error(), false);
2053 QCOMPARE(o.invoked(), 13);
2054 QCOMPARE(o.actuals().count(), 1);
2055 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2058 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
2059 QCOMPARE(o.error(), false);
2060 QCOMPARE(o.invoked(), 13);
2061 QCOMPARE(o.actuals().count(), 1);
2062 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
2065 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
2066 QCOMPARE(o.error(), false);
2067 QCOMPARE(o.invoked(), 14);
2068 QCOMPARE(o.actuals().count(), 1);
2069 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
2072 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
2073 QCOMPARE(o.error(), false);
2074 QCOMPARE(o.invoked(), 14);
2075 QCOMPARE(o.actuals().count(), 1);
2076 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
2079 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
2080 QCOMPARE(o.error(), false);
2081 QCOMPARE(o.invoked(), 14);
2082 QCOMPARE(o.actuals().count(), 1);
2083 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
2086 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
2087 QCOMPARE(o.error(), false);
2088 QCOMPARE(o.invoked(), 14);
2089 QCOMPARE(o.actuals().count(), 1);
2090 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
2093 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
2094 QCOMPARE(o.error(), false);
2095 QCOMPARE(o.invoked(), 15);
2096 QCOMPARE(o.actuals().count(), 2);
2097 QCOMPARE(o.actuals().at(0), QVariant(4));
2098 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
2101 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
2102 QCOMPARE(o.error(), false);
2103 QCOMPARE(o.invoked(), 15);
2104 QCOMPARE(o.actuals().count(), 2);
2105 QCOMPARE(o.actuals().at(0), QVariant(8));
2106 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
2109 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
2110 QCOMPARE(o.error(), false);
2111 QCOMPARE(o.invoked(), 15);
2112 QCOMPARE(o.actuals().count(), 2);
2113 QCOMPARE(o.actuals().at(0), QVariant(3));
2114 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
2117 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
2118 QCOMPARE(o.error(), false);
2119 QCOMPARE(o.invoked(), 15);
2120 QCOMPARE(o.actuals().count(), 2);
2121 QCOMPARE(o.actuals().at(0), QVariant(44));
2122 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
2125 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
2126 QCOMPARE(o.error(), false);
2127 QCOMPARE(o.invoked(), -1);
2128 QCOMPARE(o.actuals().count(), 0);
2131 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
2132 QCOMPARE(o.error(), false);
2133 QCOMPARE(o.invoked(), 16);
2134 QCOMPARE(o.actuals().count(), 1);
2135 QCOMPARE(o.actuals().at(0), QVariant(10));
2138 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
2139 QCOMPARE(o.error(), false);
2140 QCOMPARE(o.invoked(), 17);
2141 QCOMPARE(o.actuals().count(), 2);
2142 QCOMPARE(o.actuals().at(0), QVariant(10));
2143 QCOMPARE(o.actuals().at(1), QVariant(11));
2146 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2147 QCOMPARE(o.error(), false);
2148 QCOMPARE(o.invoked(), 18);
2149 QCOMPARE(o.actuals().count(), 1);
2150 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2153 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2154 QCOMPARE(o.error(), false);
2155 QCOMPARE(o.invoked(), 19);
2156 QCOMPARE(o.actuals().count(), 1);
2157 QCOMPARE(o.actuals().at(0), QVariant(9));
2160 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2161 QCOMPARE(o.error(), false);
2162 QCOMPARE(o.invoked(), 20);
2163 QCOMPARE(o.actuals().count(), 2);
2164 QCOMPARE(o.actuals().at(0), QVariant(10));
2165 QCOMPARE(o.actuals().at(1), QVariant(19));
2168 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2169 QCOMPARE(o.error(), false);
2170 QCOMPARE(o.invoked(), 20);
2171 QCOMPARE(o.actuals().count(), 2);
2172 QCOMPARE(o.actuals().at(0), QVariant(10));
2173 QCOMPARE(o.actuals().at(1), QVariant(13));
2176 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2177 QCOMPARE(o.error(), false);
2178 QCOMPARE(o.invoked(), -3);
2179 QCOMPARE(o.actuals().count(), 1);
2180 QCOMPARE(o.actuals().at(0), QVariant(9));
2183 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2184 QCOMPARE(o.error(), false);
2185 QCOMPARE(o.invoked(), 21);
2186 QCOMPARE(o.actuals().count(), 2);
2187 QCOMPARE(o.actuals().at(0), QVariant(9));
2188 QCOMPARE(o.actuals().at(1), QVariant());
2191 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2192 QCOMPARE(o.error(), false);
2193 QCOMPARE(o.invoked(), 21);
2194 QCOMPARE(o.actuals().count(), 2);
2195 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2196 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2199 // QTBUG-13047 (check that you can pass registered object types as args)
2200 void tst_qdeclarativeecmascript::invokableObjectArg()
2202 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2204 QObject *o = component.create();
2206 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2208 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2213 // QTBUG-13047 (check that you can return registered object types from methods)
2214 void tst_qdeclarativeecmascript::invokableObjectRet()
2216 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2218 QObject *o = component.create();
2220 QCOMPARE(o->property("test").toBool(), true);
2225 void tst_qdeclarativeecmascript::listToVariant()
2227 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2229 MyQmlContainer container;
2231 QDeclarativeContext context(engine.rootContext());
2232 context.setContextObject(&container);
2234 QObject *object = component.create(&context);
2235 QVERIFY(object != 0);
2237 QVariant v = object->property("test");
2238 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2239 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2245 Q_DECLARE_METATYPE(QDeclarativeListProperty<MyQmlObject>)
2246 void tst_qdeclarativeecmascript::listAssignment()
2248 QDeclarativeComponent component(&engine, TEST_FILE("listAssignment.qml"));
2249 QObject *obj = component.create();
2250 QCOMPARE(obj->property("list1length").toInt(), 2);
2251 QDeclarativeListProperty<MyQmlObject> list1 = obj->property("list1").value<QDeclarativeListProperty<MyQmlObject> >();
2252 QDeclarativeListProperty<MyQmlObject> list2 = obj->property("list2").value<QDeclarativeListProperty<MyQmlObject> >();
2253 QCOMPARE(list1.count(&list1), list2.count(&list2));
2254 QCOMPARE(list1.at(&list1, 0), list2.at(&list2, 0));
2255 QCOMPARE(list1.at(&list1, 1), list2.at(&list2, 1));
2260 void tst_qdeclarativeecmascript::multiEngineObject()
2263 obj.setStringProperty("Howdy planet");
2265 QDeclarativeEngine e1;
2266 e1.rootContext()->setContextProperty("thing", &obj);
2267 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2269 QDeclarativeEngine e2;
2270 e2.rootContext()->setContextProperty("thing", &obj);
2271 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2273 QObject *o1 = c1.create();
2274 QObject *o2 = c2.create();
2276 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2277 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2283 // Test that references to QObjects are cleanup when the object is destroyed
2284 void tst_qdeclarativeecmascript::deletedObject()
2286 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2288 QObject *object = component.create();
2290 QCOMPARE(object->property("test1").toBool(), true);
2291 QCOMPARE(object->property("test2").toBool(), true);
2292 QCOMPARE(object->property("test3").toBool(), true);
2293 QCOMPARE(object->property("test4").toBool(), true);
2298 void tst_qdeclarativeecmascript::attachedPropertyScope()
2300 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2302 QObject *object = component.create();
2303 QVERIFY(object != 0);
2305 MyQmlAttachedObject *attached =
2306 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2307 QVERIFY(attached != 0);
2309 QCOMPARE(object->property("value2").toInt(), 0);
2311 attached->emitMySignal();
2313 QCOMPARE(object->property("value2").toInt(), 9);
2318 void tst_qdeclarativeecmascript::scriptConnect()
2321 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2323 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2324 QVERIFY(object != 0);
2326 QCOMPARE(object->property("test").toBool(), false);
2327 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2328 QCOMPARE(object->property("test").toBool(), true);
2334 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2336 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2337 QVERIFY(object != 0);
2339 QCOMPARE(object->property("test").toBool(), false);
2340 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2341 QCOMPARE(object->property("test").toBool(), true);
2347 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2349 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2350 QVERIFY(object != 0);
2352 QCOMPARE(object->property("test").toBool(), false);
2353 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2354 QCOMPARE(object->property("test").toBool(), true);
2360 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2362 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2363 QVERIFY(object != 0);
2365 QCOMPARE(object->methodCalled(), false);
2366 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2367 QCOMPARE(object->methodCalled(), true);
2373 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2375 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2376 QVERIFY(object != 0);
2378 QCOMPARE(object->methodCalled(), false);
2379 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2380 QCOMPARE(object->methodCalled(), true);
2386 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2388 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2389 QVERIFY(object != 0);
2391 QCOMPARE(object->property("test").toInt(), 0);
2392 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2393 QCOMPARE(object->property("test").toInt(), 2);
2399 void tst_qdeclarativeecmascript::scriptDisconnect()
2402 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2404 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2405 QVERIFY(object != 0);
2407 QCOMPARE(object->property("test").toInt(), 0);
2408 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2409 QCOMPARE(object->property("test").toInt(), 1);
2410 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2411 QCOMPARE(object->property("test").toInt(), 2);
2412 emit object->basicSignal();
2413 QCOMPARE(object->property("test").toInt(), 2);
2414 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2415 QCOMPARE(object->property("test").toInt(), 2);
2421 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2423 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2424 QVERIFY(object != 0);
2426 QCOMPARE(object->property("test").toInt(), 0);
2427 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2428 QCOMPARE(object->property("test").toInt(), 1);
2429 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2430 QCOMPARE(object->property("test").toInt(), 2);
2431 emit object->basicSignal();
2432 QCOMPARE(object->property("test").toInt(), 2);
2433 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2434 QCOMPARE(object->property("test").toInt(), 2);
2440 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2442 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2443 QVERIFY(object != 0);
2445 QCOMPARE(object->property("test").toInt(), 0);
2446 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2447 QCOMPARE(object->property("test").toInt(), 1);
2448 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2449 QCOMPARE(object->property("test").toInt(), 2);
2450 emit object->basicSignal();
2451 QCOMPARE(object->property("test").toInt(), 2);
2452 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2453 QCOMPARE(object->property("test").toInt(), 3);
2458 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2460 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2461 QVERIFY(object != 0);
2463 QCOMPARE(object->property("test").toInt(), 0);
2464 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2465 QCOMPARE(object->property("test").toInt(), 1);
2466 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2467 QCOMPARE(object->property("test").toInt(), 2);
2468 emit object->basicSignal();
2469 QCOMPARE(object->property("test").toInt(), 2);
2470 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2471 QCOMPARE(object->property("test").toInt(), 3);
2477 class OwnershipObject : public QObject
2481 OwnershipObject() { object = new QObject; }
2483 QPointer<QObject> object;
2486 QObject *getObject() { return object; }
2489 void tst_qdeclarativeecmascript::ownership()
2491 OwnershipObject own;
2492 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2493 context->setContextObject(&own);
2496 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2498 QVERIFY(own.object != 0);
2500 QObject *object = component.create(context);
2502 engine.collectGarbage();
2504 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2506 QVERIFY(own.object == 0);
2511 own.object = new QObject(&own);
2514 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2516 QVERIFY(own.object != 0);
2518 QObject *object = component.create(context);
2520 engine.collectGarbage();
2522 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2524 QVERIFY(own.object != 0);
2532 class CppOwnershipReturnValue : public QObject
2536 CppOwnershipReturnValue() : value(0) {}
2537 ~CppOwnershipReturnValue() { delete value; }
2539 Q_INVOKABLE QObject *create() {
2540 value = new QObject;
2541 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2545 Q_INVOKABLE MyQmlObject *createQmlObject() {
2546 MyQmlObject *rv = new MyQmlObject;
2551 QPointer<QObject> value;
2555 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2556 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2558 CppOwnershipReturnValue source;
2561 QDeclarativeEngine engine;
2562 engine.rootContext()->setContextProperty("source", &source);
2564 QVERIFY(source.value == 0);
2566 QDeclarativeComponent component(&engine);
2567 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2569 QObject *object = component.create();
2571 QVERIFY(object != 0);
2572 QVERIFY(source.value != 0);
2577 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2579 QVERIFY(source.value != 0);
2583 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2585 CppOwnershipReturnValue source;
2588 QDeclarativeEngine engine;
2589 engine.rootContext()->setContextProperty("source", &source);
2591 QVERIFY(source.value == 0);
2593 QDeclarativeComponent component(&engine);
2594 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2596 QObject *object = component.create();
2598 QVERIFY(object != 0);
2599 QVERIFY(source.value != 0);
2604 engine.collectGarbage();
2605 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2607 QVERIFY(source.value == 0);
2610 class QListQObjectMethodsObject : public QObject
2614 QListQObjectMethodsObject() {
2615 m_objects.append(new MyQmlObject());
2616 m_objects.append(new MyQmlObject());
2619 ~QListQObjectMethodsObject() {
2620 qDeleteAll(m_objects);
2624 QList<QObject *> getObjects() { return m_objects; }
2627 QList<QObject *> m_objects;
2630 // Tests that returning a QList<QObject*> from a method works
2631 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2633 QListQObjectMethodsObject obj;
2634 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2635 context->setContextObject(&obj);
2637 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2639 QObject *object = component.create(context);
2641 QCOMPARE(object->property("test").toInt(), 2);
2642 QCOMPARE(object->property("test2").toBool(), true);
2649 void tst_qdeclarativeecmascript::strictlyEquals()
2651 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2653 QObject *object = component.create();
2654 QVERIFY(object != 0);
2656 QCOMPARE(object->property("test1").toBool(), true);
2657 QCOMPARE(object->property("test2").toBool(), true);
2658 QCOMPARE(object->property("test3").toBool(), true);
2659 QCOMPARE(object->property("test4").toBool(), true);
2660 QCOMPARE(object->property("test5").toBool(), true);
2661 QCOMPARE(object->property("test6").toBool(), true);
2662 QCOMPARE(object->property("test7").toBool(), true);
2663 QCOMPARE(object->property("test8").toBool(), true);
2668 void tst_qdeclarativeecmascript::compiled()
2670 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2672 QObject *object = component.create();
2673 QVERIFY(object != 0);
2675 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2676 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2677 QCOMPARE(object->property("test3").toBool(), true);
2678 QCOMPARE(object->property("test4").toBool(), false);
2679 QCOMPARE(object->property("test5").toBool(), false);
2680 QCOMPARE(object->property("test6").toBool(), true);
2682 QCOMPARE(object->property("test7").toInt(), 185);
2683 QCOMPARE(object->property("test8").toInt(), 167);
2684 QCOMPARE(object->property("test9").toBool(), true);
2685 QCOMPARE(object->property("test10").toBool(), false);
2686 QCOMPARE(object->property("test11").toBool(), false);
2687 QCOMPARE(object->property("test12").toBool(), true);
2689 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2690 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2691 QCOMPARE(object->property("test15").toBool(), false);
2692 QCOMPARE(object->property("test16").toBool(), true);
2694 QCOMPARE(object->property("test17").toInt(), 5);
2695 QCOMPARE(object->property("test18").toReal(), qreal(176));
2696 QCOMPARE(object->property("test19").toInt(), 7);
2697 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2698 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2699 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2700 QCOMPARE(object->property("test23").toBool(), true);
2701 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2702 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2707 // Test that numbers assigned in bindings as strings work consistently
2708 void tst_qdeclarativeecmascript::numberAssignment()
2710 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2712 QObject *object = component.create();
2713 QVERIFY(object != 0);
2715 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2716 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2717 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2718 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2719 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2721 QCOMPARE(object->property("test5"), QVariant((int)7));
2722 QCOMPARE(object->property("test6"), QVariant((int)7));
2723 QCOMPARE(object->property("test7"), QVariant((int)6));
2724 QCOMPARE(object->property("test8"), QVariant((int)6));
2726 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2727 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2728 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2729 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2734 void tst_qdeclarativeecmascript::propertySplicing()
2736 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2738 QObject *object = component.create();
2739 QVERIFY(object != 0);
2741 QCOMPARE(object->property("test").toBool(), true);
2747 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2749 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2751 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2752 QVERIFY(object != 0);
2754 MyQmlObject::MyType type;
2755 type.value = 0x8971123;
2756 emit object->signalWithUnknownType(type);
2758 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2760 QCOMPARE(result.value, type.value);
2766 void tst_qdeclarativeecmascript::signalWithJSValueInVariant_data()
2768 QTest::addColumn<QString>("expression");
2769 QTest::addColumn<QString>("compare");
2771 QString compareStrict("(function(a, b) { return a === b; })");
2772 QTest::newRow("true") << "true" << compareStrict;
2773 QTest::newRow("undefined") << "undefined" << compareStrict;
2774 QTest::newRow("null") << "null" << compareStrict;
2775 QTest::newRow("123") << "123" << compareStrict;
2776 QTest::newRow("'ciao'") << "'ciao'" << compareStrict;
2778 QString comparePropertiesStrict(
2780 " if (typeof b != 'object')"
2782 " var props = Object.getOwnPropertyNames(b);"
2783 " for (var i = 0; i < props.length; ++i) {"
2784 " var p = props[i];"
2785 " return arguments.callee(a[p], b[p]);"
2788 QTest::newRow("{ foo: 'bar' }") << "({ foo: 'bar' })" << comparePropertiesStrict;
2789 QTest::newRow("[10,20,30]") << "[10,20,30]" << comparePropertiesStrict;
2792 void tst_qdeclarativeecmascript::signalWithJSValueInVariant()
2794 QFETCH(QString, expression);
2795 QFETCH(QString, compare);
2797 QDeclarativeComponent component(&engine, TEST_FILE("signalWithJSValueInVariant.qml"));
2798 QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
2799 QVERIFY(object != 0);
2801 QJSValue value = engine.evaluate(expression);
2802 QVERIFY(!engine.hasUncaughtException());
2803 object->setProperty("expression", expression);
2804 object->setProperty("compare", compare);
2805 object->setProperty("pass", false);
2807 emit object->signalWithVariant(QVariant::fromValue(value));
2808 QVERIFY(object->property("pass").toBool());
2811 void tst_qdeclarativeecmascript::signalWithJSValueInVariant_twoEngines_data()
2813 signalWithJSValueInVariant_data();
2816 void tst_qdeclarativeecmascript::signalWithJSValueInVariant_twoEngines()
2818 QFETCH(QString, expression);
2819 QFETCH(QString, compare);
2821 QDeclarativeComponent component(&engine, TEST_FILE("signalWithJSValueInVariant.qml"));
2822 QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
2823 QVERIFY(object != 0);
2826 QJSValue value = engine2.evaluate(expression);
2827 QVERIFY(!engine2.hasUncaughtException());
2828 object->setProperty("expression", expression);
2829 object->setProperty("compare", compare);
2830 object->setProperty("pass", false);
2832 QTest::ignoreMessage(QtWarningMsg, "JSValue can't be rassigned to an another engine.");
2833 emit object->signalWithVariant(QVariant::fromValue(value));
2834 QVERIFY(!object->property("pass").toBool());
2837 void tst_qdeclarativeecmascript::moduleApi_data()
2839 QTest::addColumn<QUrl>("testfile");
2840 QTest::addColumn<QString>("errorMessage");
2841 QTest::addColumn<QStringList>("warningMessages");
2842 QTest::addColumn<QStringList>("readProperties");
2843 QTest::addColumn<QVariantList>("readExpectedValues");
2844 QTest::addColumn<QStringList>("writeProperties");
2845 QTest::addColumn<QVariantList>("writeValues");
2846 QTest::addColumn<QStringList>("readBackProperties");
2847 QTest::addColumn<QVariantList>("readBackExpectedValues");
2849 QTest::newRow("qobject, register + read + method")
2850 << TEST_FILE("moduleapi/qobjectModuleApi.qml")
2853 << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest"
2854 << "qobjectMinorVersionTest" << "qobjectMajorVersionTest" << "qobjectParentedTest")
2855 << (QVariantList() << 20 << 20 << 1 << 20 << 20 << 26)
2861 QTest::newRow("script, register + read")
2862 << TEST_FILE("moduleapi/scriptModuleApi.qml")
2865 << (QStringList() << "scriptTest")
2866 << (QVariantList() << 13)
2872 QTest::newRow("qobject, caching + read")
2873 << TEST_FILE("moduleapi/qobjectModuleApiCaching.qml")
2876 << (QStringList() << "existingUriTest" << "qobjectParentedTest")
2877 << (QVariantList() << 20 << 26) // 26, shouldn't have incremented to 27.
2883 QTest::newRow("script, caching + read")
2884 << TEST_FILE("moduleapi/scriptModuleApiCaching.qml")
2887 << (QStringList() << "scriptTest")
2888 << (QVariantList() << 13) // 13, shouldn't have incremented to 14.
2894 QTest::newRow("qobject, writing + readonly constraints")
2895 << TEST_FILE("moduleapi/qobjectModuleApiWriting.qml")
2897 << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":14: Error: Cannot assign to read-only property \"qobjectTestProperty\"")))
2898 << (QStringList() << "readOnlyProperty" << "writableProperty")
2899 << (QVariantList() << 20 << 50)
2900 << (QStringList() << "firstProperty" << "writableProperty")
2901 << (QVariantList() << 30 << 30)
2902 << (QStringList() << "readOnlyProperty" << "writableProperty")
2903 << (QVariantList() << 20 << 30);
2905 QTest::newRow("script, writing + readonly constraints")
2906 << TEST_FILE("moduleapi/scriptModuleApiWriting.qml")
2908 << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/scriptModuleApiWriting.qml").toLocalFile() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\"")))
2909 << (QStringList() << "readBack" << "unchanged")
2910 << (QVariantList() << 13 << 42)
2911 << (QStringList() << "firstProperty" << "secondProperty")
2912 << (QVariantList() << 30 << 30)
2913 << (QStringList() << "readBack" << "unchanged")
2914 << (QVariantList() << 30 << 42);
2916 QTest::newRow("qobject module API enum values in JS")
2917 << TEST_FILE("moduleapi/qobjectModuleApiEnums.qml")
2920 << (QStringList() << "enumValue" << "enumMethod")
2921 << (QVariantList() << 42 << 30)
2927 QTest::newRow("qobject, invalid major version fail")
2928 << TEST_FILE("moduleapi/moduleApiMajorVersionFail.qml")
2929 << QString("QDeclarativeComponent: Component is not ready")
2938 QTest::newRow("qobject, invalid minor version fail")
2939 << TEST_FILE("moduleapi/moduleApiMinorVersionFail.qml")
2940 << QString("QDeclarativeComponent: Component is not ready")
2950 void tst_qdeclarativeecmascript::moduleApi()
2952 QFETCH(QUrl, testfile);
2953 QFETCH(QString, errorMessage);
2954 QFETCH(QStringList, warningMessages);
2955 QFETCH(QStringList, readProperties);
2956 QFETCH(QVariantList, readExpectedValues);
2957 QFETCH(QStringList, writeProperties);
2958 QFETCH(QVariantList, writeValues);
2959 QFETCH(QStringList, readBackProperties);
2960 QFETCH(QVariantList, readBackExpectedValues);
2962 QDeclarativeComponent component(&engine, testfile);
2964 if (!errorMessage.isEmpty())
2965 QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData());
2967 if (warningMessages.size())
2968 foreach (const QString &warning, warningMessages)
2969 QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
2971 QObject *object = component.create();
2972 if (!errorMessage.isEmpty()) {
2973 QVERIFY(object == 0);
2975 QVERIFY(object != 0);
2976 for (int i = 0; i < readProperties.size(); ++i)
2977 QCOMPARE(object->property(readProperties.at(i).toAscii().constData()), readExpectedValues.at(i));
2978 for (int i = 0; i < writeProperties.size(); ++i)
2979 QVERIFY(object->setProperty(writeProperties.at(i).toAscii().constData(), writeValues.at(i)));
2980 for (int i = 0; i < readBackProperties.size(); ++i)
2981 QCOMPARE(object->property(readBackProperties.at(i).toAscii().constData()), readBackExpectedValues.at(i));
2986 void tst_qdeclarativeecmascript::importScripts()
2988 QObject *object = 0;
2990 // first, ensure that the required behaviour works.
2991 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2992 object = component.create();
2993 QVERIFY(object != 0);
2994 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2995 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2996 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2997 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
3000 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
3001 object = componentTwo.create();
3002 QVERIFY(object != 0);
3003 QCOMPARE(object->property("componentError"), QVariant(5));
3006 // then, ensure that unintended behaviour does not work.
3007 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
3008 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
3009 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3010 object = failOneComponent.create();
3011 QVERIFY(object != 0);
3012 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
3014 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
3015 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
3016 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3017 object = failTwoComponent.create();
3018 QVERIFY(object != 0);
3019 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
3021 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
3022 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
3023 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3024 object = failThreeComponent.create();
3025 QVERIFY(object != 0);
3026 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
3028 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
3029 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
3030 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3031 object = failFourComponent.create();
3032 QVERIFY(object != 0);
3033 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
3035 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
3036 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
3037 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3038 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
3039 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
3040 object = failFiveComponent.create();
3041 QVERIFY(object != 0);
3042 QCOMPARE(object->property("componentError"), QVariant(0));
3045 // also, test that importing scripts with .pragma library works as required
3046 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
3047 object = pragmaLibraryComponent.create();
3048 QVERIFY(object != 0);
3049 QCOMPARE(object->property("testValue"), QVariant(31));
3052 // and that .pragma library scripts don't inherit imports from any .qml file
3053 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
3054 object = pragmaLibraryComponentTwo.create();
3055 QVERIFY(object != 0);
3056 QCOMPARE(object->property("testValue"), QVariant(0));
3060 void tst_qdeclarativeecmascript::scarceResources()
3062 QPixmap origPixmap(100, 100);
3063 origPixmap.fill(Qt::blue);
3065 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
3066 ScarceResourceObject *eo = 0;
3067 QObject *object = 0;
3069 // in the following three cases, the instance created from the component
3070 // has a property which is a copy of the scarce resource; hence, the
3071 // resource should NOT be detached prior to deletion of the object instance,
3072 // unless the resource is destroyed explicitly.
3073 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
3074 object = component.create();
3075 QVERIFY(object != 0);
3076 QVERIFY(object->property("scarceResourceCopy").isValid());
3077 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3078 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3079 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3080 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
3083 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
3084 object = componentTwo.create();
3085 QVERIFY(object != 0);
3086 QVERIFY(object->property("scarceResourceCopy").isValid());
3087 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3088 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3089 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3090 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
3093 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
3094 object = componentThree.create();
3095 QVERIFY(object != 0);
3096 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
3097 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3098 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3099 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
3102 // in the following three cases, no other copy should exist in memory,
3103 // and so it should be detached (unless explicitly preserved).
3104 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
3105 object = componentFour.create();
3106 QVERIFY(object != 0);
3107 QVERIFY(object->property("scarceResourceTest").isValid());
3108 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3109 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3110 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3111 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
3114 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
3115 object = componentFive.create();
3116 QVERIFY(object != 0);
3117 QVERIFY(object->property("scarceResourceTest").isValid());
3118 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3119 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3120 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3121 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
3124 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
3125 object = componentSix.create();
3126 QVERIFY(object != 0);
3127 QVERIFY(object->property("scarceResourceTest").isValid());
3128 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3129 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3130 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3131 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
3134 // test that scarce resources are handled correctly for imports
3135 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
3136 object = componentSeven.create();
3137 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
3138 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
3141 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
3142 object = componentEight.create();
3143 QVERIFY(object != 0);
3144 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
3145 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3148 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
3149 object = componentNine.create();
3150 QVERIFY(object != 0);
3151 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
3152 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3153 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
3154 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
3155 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
3156 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
3159 // test that scarce resources are handled properly in signal invocation
3160 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
3161 object = componentTen.create();
3162 QVERIFY(object != 0);
3163 QObject *srsc = object->findChild<QObject*>("srsc");
3165 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
3166 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
3167 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3168 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3169 QMetaObject::invokeMethod(srsc, "testSignal");
3170 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
3171 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
3172 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3173 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
3174 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
3175 QVERIFY(srsc->property("scarceResourceCopy").isValid());
3176 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3177 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3178 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
3179 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3182 // test that scarce resources are handled properly from js functions in qml files
3183 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
3184 object = componentEleven.create();
3185 QVERIFY(object != 0);
3186 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3187 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3188 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3189 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3190 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
3191 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3192 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3193 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
3194 QMetaObject::invokeMethod(object, "releaseScarceResource");
3195 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
3196 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3197 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3198 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3201 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
3202 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
3203 object = componentTwelve.create();
3204 QVERIFY(object != 0);
3205 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3206 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3207 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3208 QString srp_name = object->property("srp_name").toString();
3209 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
3210 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
3211 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3212 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
3213 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3214 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3215 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3219 void tst_qdeclarativeecmascript::propertyChangeSlots()
3221 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
3222 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
3223 QObject *object = component.create();
3224 QVERIFY(object != 0);
3227 // ensure that invalid property names fail properly.
3228 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3229 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
3230 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
3231 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
3232 object = e1.create();
3233 QVERIFY(object == 0);
3236 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3237 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
3238 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
3239 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
3240 object = e2.create();
3241 QVERIFY(object == 0);
3244 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3245 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
3246 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
3247 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
3248 object = e3.create();
3249 QVERIFY(object == 0);
3252 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3253 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
3254 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
3255 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
3256 object = e4.create();
3257 QVERIFY(object == 0);
3261 // Ensure that QObject type conversion works on binding assignment
3262 void tst_qdeclarativeecmascript::elementAssign()
3264 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
3266 QObject *object = component.create();
3267 QVERIFY(object != 0);
3269 QCOMPARE(object->property("test").toBool(), true);
3275 void tst_qdeclarativeecmascript::objectPassThroughSignals()
3277 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
3279 QObject *object = component.create();
3280 QVERIFY(object != 0);
3282 QCOMPARE(object->property("test").toBool(), true);
3288 void tst_qdeclarativeecmascript::booleanConversion()
3290 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
3292 QObject *object = component.create();
3293 QVERIFY(object != 0);
3295 QCOMPARE(object->property("test_true1").toBool(), true);
3296 QCOMPARE(object->property("test_true2").toBool(), true);
3297 QCOMPARE(object->property("test_true3").toBool(), true);
3298 QCOMPARE(object->property("test_true4").toBool(), true);
3299 QCOMPARE(object->property("test_true5").toBool(), true);
3301 QCOMPARE(object->property("test_false1").toBool(), false);
3302 QCOMPARE(object->property("test_false2").toBool(), false);
3303 QCOMPARE(object->property("test_false3").toBool(), false);
3308 void tst_qdeclarativeecmascript::handleReferenceManagement()
3313 // Linear QObject reference
3314 QDeclarativeEngine hrmEngine;
3315 QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.object.1.qml"));
3316 QObject *object = component.create();
3317 QVERIFY(object != 0);
3318 CircularReferenceObject *cro = object->findChild<CircularReferenceObject*>("cro");
3319 cro->setDtorCount(&dtorCount);
3320 QMetaObject::invokeMethod(object, "createReference");
3321 QMetaObject::invokeMethod(object, "performGc");
3322 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3323 QCOMPARE(dtorCount, 0); // second has JS ownership, kept alive by first's reference
3325 hrmEngine.collectGarbage();
3326 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3327 QCOMPARE(dtorCount, 3);
3332 // Circular QObject reference
3333 QDeclarativeEngine hrmEngine;
3334 QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.object.2.qml"));
3335 QObject *object = component.create();
3336 QVERIFY(object != 0);
3337 CircularReferenceObject *cro = object->findChild<CircularReferenceObject*>("cro");
3338 cro->setDtorCount(&dtorCount);
3339 QMetaObject::invokeMethod(object, "circularReference");
3340 QMetaObject::invokeMethod(object, "performGc");
3341 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3342 QCOMPARE(dtorCount, 2); // both should be cleaned up, since circular references shouldn't keep alive.
3344 hrmEngine.collectGarbage();
3345 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3346 QCOMPARE(dtorCount, 3);
3351 // Linear handle reference
3352 QDeclarativeEngine hrmEngine;
3353 QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3354 QObject *object = component.create();
3355 QVERIFY(object != 0);
3356 CircularReferenceHandle *crh = object->findChild<CircularReferenceHandle*>("crh");
3358 crh->setDtorCount(&dtorCount);
3359 QMetaObject::invokeMethod(object, "createReference");
3360 CircularReferenceHandle *first = object->property("first").value<CircularReferenceHandle*>();
3361 CircularReferenceHandle *second = object->property("second").value<CircularReferenceHandle*>();
3362 QVERIFY(first != 0);
3363 QVERIFY(second != 0);
3364 first->addReference(QDeclarativeData::get(second)->v8object); // create reference
3365 // now we have to reparent second and make second owned by JS.
3366 second->setParent(0);
3367 QDeclarativeEngine::setObjectOwnership(second, QDeclarativeEngine::JavaScriptOwnership);
3368 QMetaObject::invokeMethod(object, "performGc");
3369 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3370 QCOMPARE(dtorCount, 0); // due to reference from first to second, second shouldn't be collected.
3372 hrmEngine.collectGarbage();
3373 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3374 QCOMPARE(dtorCount, 3);
3379 // Circular handle reference
3380 QDeclarativeEngine hrmEngine;
3381 QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.handle.2.qml"));
3382 QObject *object = component.create();
3383 QVERIFY(object != 0);
3384 CircularReferenceHandle *crh = object->findChild<CircularReferenceHandle*>("crh");
3386 crh->setDtorCount(&dtorCount);
3387 QMetaObject::invokeMethod(object, "circularReference");
3388 CircularReferenceHandle *first = object->property("first").value<CircularReferenceHandle*>();
3389 CircularReferenceHandle *second = object->property("second").value<CircularReferenceHandle*>();
3390 QVERIFY(first != 0);
3391 QVERIFY(second != 0);
3392 first->addReference(QDeclarativeData::get(second)->v8object); // create circular reference
3393 second->addReference(QDeclarativeData::get(first)->v8object); // note: must be weak.
3394 // now we have to reparent and change ownership.
3395 first->setParent(0);
3396 second->setParent(0);
3397 QDeclarativeEngine::setObjectOwnership(first, QDeclarativeEngine::JavaScriptOwnership);
3398 QDeclarativeEngine::setObjectOwnership(second, QDeclarativeEngine::JavaScriptOwnership);
3399 QMetaObject::invokeMethod(object, "performGc");
3400 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3401 QCOMPARE(dtorCount, 2); // despite circular references, both will be collected.
3403 hrmEngine.collectGarbage();
3404 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3405 QCOMPARE(dtorCount, 3);
3410 // multiple engine interaction - linear reference
3411 QDeclarativeEngine hrmEngine1;
3412 QDeclarativeEngine hrmEngine2;
3413 QDeclarativeComponent component1(&hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3414 QDeclarativeComponent component2(&hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3415 QObject *object1 = component1.create();
3416 QObject *object2 = component2.create();
3417 QVERIFY(object1 != 0);
3418 QVERIFY(object2 != 0);
3419 CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
3420 CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
3423 crh1->setDtorCount(&dtorCount);
3424 crh2->setDtorCount(&dtorCount);
3425 QMetaObject::invokeMethod(object1, "createReference");
3426 QMetaObject::invokeMethod(object2, "createReference");
3427 CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
3428 CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
3429 CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
3430 CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
3431 QVERIFY(first1 != 0);
3432 QVERIFY(second1 != 0);
3433 QVERIFY(first2 != 0);
3434 QVERIFY(second2 != 0);
3435 first1->addReference(QDeclarativeData::get(second2)->v8object); // create reference across engines
3436 // now we have to reparent second2 and make second2 owned by JS.
3437 second2->setParent(0);
3438 QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
3439 QMetaObject::invokeMethod(object1, "performGc");
3440 QMetaObject::invokeMethod(object2, "performGc");
3441 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3442 QCOMPARE(dtorCount, 0); // due to reference from first1 to second2, second2 shouldn't be collected.
3445 hrmEngine1.collectGarbage();
3446 hrmEngine2.collectGarbage();
3447 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3448 QCOMPARE(dtorCount, 6);
3453 // multiple engine interaction - circular reference
3454 QDeclarativeEngine hrmEngine1;
3455 QDeclarativeEngine hrmEngine2;
3456 QDeclarativeComponent component1(&hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3457 QDeclarativeComponent component2(&hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3458 QObject *object1 = component1.create();
3459 QObject *object2 = component2.create();
3460 QVERIFY(object1 != 0);
3461 QVERIFY(object2 != 0);
3462 CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
3463 CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
3466 crh1->setDtorCount(&dtorCount);
3467 crh2->setDtorCount(&dtorCount);
3468 QMetaObject::invokeMethod(object1, "createReference");
3469 QMetaObject::invokeMethod(object2, "createReference");
3470 CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
3471 CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
3472 CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
3473 CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
3474 QVERIFY(first1 != 0);
3475 QVERIFY(second1 != 0);
3476 QVERIFY(first2 != 0);
3477 QVERIFY(second2 != 0);
3478 first1->addReference(QDeclarativeData::get(second1)->v8object); // create linear reference within engine1
3479 second1->addReference(QDeclarativeData::get(second2)->v8object); // create linear reference across engines
3480 second2->addReference(QDeclarativeData::get(first2)->v8object); // create linear reference within engine2
3481 first2->addReference(QDeclarativeData::get(first1)->v8object); // close the loop - circular ref across engines
3482 // now we have to reparent and change ownership to JS.
3483 first1->setParent(0);
3484 second1->setParent(0);
3485 first2->setParent(0);
3486 second2->setParent(0);
3487 QDeclarativeEngine::setObjectOwnership(first1, QDeclarativeEngine::JavaScriptOwnership);
3488 QDeclarativeEngine::setObjectOwnership(second1, QDeclarativeEngine::JavaScriptOwnership);
3489 QDeclarativeEngine::setObjectOwnership(first2, QDeclarativeEngine::JavaScriptOwnership);
3490 QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
3491 QMetaObject::invokeMethod(object1, "performGc");
3492 QMetaObject::invokeMethod(object2, "performGc");
3493 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3494 QCOMPARE(dtorCount, 4); // circular references shouldn't keep them alive.
3497 hrmEngine1.collectGarbage();
3498 hrmEngine2.collectGarbage();
3499 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3500 QCOMPARE(dtorCount, 6);
3505 // multiple engine interaction - linear reference with engine deletion
3506 QDeclarativeEngine *hrmEngine1 = new QDeclarativeEngine;
3507 QDeclarativeEngine *hrmEngine2 = new QDeclarativeEngine;
3508 QDeclarativeComponent component1(hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3509 QDeclarativeComponent component2(hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
3510 QObject *object1 = component1.create();
3511 QObject *object2 = component2.create();
3512 QVERIFY(object1 != 0);
3513 QVERIFY(object2 != 0);
3514 CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
3515 CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
3518 crh1->setDtorCount(&dtorCount);
3519 crh2->setDtorCount(&dtorCount);
3520 QMetaObject::invokeMethod(object1, "createReference");
3521 QMetaObject::invokeMethod(object2, "createReference");
3522 CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
3523 CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
3524 CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
3525 CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
3526 QVERIFY(first1 != 0);
3527 QVERIFY(second1 != 0);
3528 QVERIFY(first2 != 0);
3529 QVERIFY(second2 != 0);
3530 first1->addReference(QDeclarativeData::get(second1)->v8object); // create linear reference within engine1
3531 second1->addReference(QDeclarativeData::get(second2)->v8object); // create linear reference across engines
3532 second2->addReference(QDeclarativeData::get(first2)->v8object); // create linear reference within engine2
3533 // now we have to reparent and change ownership to JS.
3534 first1->setParent(crh1);
3535 second1->setParent(0);
3536 first2->setParent(0);
3537 second2->setParent(0);
3538 QDeclarativeEngine::setObjectOwnership(second1, QDeclarativeEngine::JavaScriptOwnership);
3539 QDeclarativeEngine::setObjectOwnership(first2, QDeclarativeEngine::JavaScriptOwnership);
3540 QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
3541 QMetaObject::invokeMethod(object1, "performGc");
3542 QMetaObject::invokeMethod(object2, "performGc");
3543 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3544 QCOMPARE(dtorCount, 0);
3546 QMetaObject::invokeMethod(object1, "performGc");
3547 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3548 QCOMPARE(dtorCount, 0);
3551 hrmEngine1->collectGarbage();
3552 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
3553 QCOMPARE(dtorCount, 6);
3558 void tst_qdeclarativeecmascript::stringArg()
3560 QDeclarativeComponent component(&engine, TEST_FILE("stringArg.qml"));
3561 QObject *object = component.create();
3562 QVERIFY(object != 0);
3563 QMetaObject::invokeMethod(object, "success");
3564 QVERIFY(object->property("returnValue").toBool());
3566 QString w1 = TEST_FILE("stringArg.qml").toString() + QLatin1String(":45: Error: String.arg(): Invalid arguments");
3567 QTest::ignoreMessage(QtWarningMsg, w1.toAscii().constData());
3568 QMetaObject::invokeMethod(object, "failure");
3569 QVERIFY(object->property("returnValue").toBool());
3574 // Test that assigning a null object works
3575 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
3576 void tst_qdeclarativeecmascript::nullObjectBinding()
3578 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
3580 QObject *object = component.create();
3581 QVERIFY(object != 0);
3583 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3588 // Test that bindings don't evaluate once the engine has been destroyed
3589 void tst_qdeclarativeecmascript::deletedEngine()
3591 QDeclarativeEngine *engine = new QDeclarativeEngine;
3592 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3594 QObject *object = component.create();
3595 QVERIFY(object != 0);
3597 QCOMPARE(object->property("a").toInt(), 39);
3598 object->setProperty("b", QVariant(9));
3599 QCOMPARE(object->property("a").toInt(), 117);
3603 QCOMPARE(object->property("a").toInt(), 117);
3604 object->setProperty("b", QVariant(10));
3605 QCOMPARE(object->property("a").toInt(), 117);
3610 // Test the crashing part of QTBUG-9705
3611 void tst_qdeclarativeecmascript::libraryScriptAssert()
3613 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3615 QObject *object = component.create();
3616 QVERIFY(object != 0);
3621 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3623 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3625 QObject *object = component.create();
3626 QVERIFY(object != 0);
3628 QCOMPARE(object->property("test1").toInt(), 10);
3629 QCOMPARE(object->property("test2").toInt(), 11);
3631 object->setProperty("runTest", true);
3633 QCOMPARE(object->property("test1"), QVariant());
3634 QCOMPARE(object->property("test2"), QVariant());
3640 void tst_qdeclarativeecmascript::qtbug_9792()
3642 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3644 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3646 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3647 QVERIFY(object != 0);
3649 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3650 object->basicSignal();
3654 transientErrorsMsgCount = 0;
3655 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3657 object->basicSignal();
3659 qInstallMsgHandler(old);
3661 QCOMPARE(transientErrorsMsgCount, 0);
3666 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3667 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3669 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3671 QObject *o = component.create();
3674 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3675 QVERIFY(nested != 0);
3677 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3680 nested = qvariant_cast<QObject *>(o->property("object"));
3681 QVERIFY(nested == 0);
3683 // If the bug is present, the next line will crash
3687 // Test that we shut down without stupid warnings
3688 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3691 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3693 QObject *o = component.create();
3695 transientErrorsMsgCount = 0;
3696 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3700 qInstallMsgHandler(old);
3702 QCOMPARE(transientErrorsMsgCount, 0);
3707 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3709 QObject *o = component.create();
3711 transientErrorsMsgCount = 0;
3712 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3716 qInstallMsgHandler(old);
3718 QCOMPARE(transientErrorsMsgCount, 0);
3722 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3725 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3727 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3730 QVERIFY(o->objectProperty() != 0);
3732 o->setProperty("runTest", true);
3734 QVERIFY(o->objectProperty() == 0);
3740 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3742 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3745 QVERIFY(o->objectProperty() == 0);
3751 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3753 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3755 QString url = component.url().toString();
3756 QString warning = url + ":4: Unable to assign a function to a property.";
3757 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3759 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3762 QVERIFY(!o->property("a").isValid());
3767 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3769 QFETCH(QString, triggerProperty);
3771 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3772 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3774 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3776 QVERIFY(!o->property("a").isValid());
3778 o->setProperty("aNumber", QVariant(5));
3779 o->setProperty(triggerProperty.toUtf8().constData(), true);
3780 QCOMPARE(o->property("a"), QVariant(50));
3782 o->setProperty("aNumber", QVariant(10));
3783 QCOMPARE(o->property("a"), QVariant(100));
3788 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3790 QTest::addColumn<QString>("triggerProperty");
3792 QTest::newRow("assign to property") << "assignToProperty";
3793 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3795 QTest::newRow("assign to value type") << "assignToValueType";
3797 QTest::newRow("use 'this'") << "assignWithThis";
3798 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3801 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3803 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3804 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3806 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3808 QVERIFY(!o->property("a").isValid());
3810 o->setProperty("assignFuncWithoutReturn", true);
3811 QVERIFY(!o->property("a").isValid());
3813 QString url = component.url().toString();
3814 QString warning = url + ":67: Unable to assign QString to int";
3815 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3816 o->setProperty("assignWrongType", true);
3818 warning = url + ":71: Unable to assign QString to int";
3819 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3820 o->setProperty("assignWrongTypeToValueType", true);
3825 void tst_qdeclarativeecmascript::eval()
3827 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3829 QObject *o = component.create();
3832 QCOMPARE(o->property("test1").toBool(), true);
3833 QCOMPARE(o->property("test2").toBool(), true);
3834 QCOMPARE(o->property("test3").toBool(), true);
3835 QCOMPARE(o->property("test4").toBool(), true);
3836 QCOMPARE(o->property("test5").toBool(), true);
3841 void tst_qdeclarativeecmascript::function()
3843 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3845 QObject *o = component.create();
3848 QCOMPARE(o->property("test1").toBool(), true);
3849 QCOMPARE(o->property("test2").toBool(), true);
3850 QCOMPARE(o->property("test3").toBool(), true);
3855 // Test the "Qt.include" method
3856 void tst_qdeclarativeecmascript::include()
3858 // Non-library relative include
3860 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3861 QObject *o = component.create();
3864 QCOMPARE(o->property("test0").toInt(), 99);
3865 QCOMPARE(o->property("test1").toBool(), true);
3866 QCOMPARE(o->property("test2").toBool(), true);
3867 QCOMPARE(o->property("test2_1").toBool(), true);
3868 QCOMPARE(o->property("test3").toBool(), true);
3869 QCOMPARE(o->property("test3_1").toBool(), true);
3874 // Library relative include
3876 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3877 QObject *o = component.create();
3880 QCOMPARE(o->property("test0").toInt(), 99);
3881 QCOMPARE(o->property("test1").toBool(), true);
3882 QCOMPARE(o->property("test2").toBool(), true);
3883 QCOMPARE(o->property("test2_1").toBool(), true);
3884 QCOMPARE(o->property("test3").toBool(), true);
3885 QCOMPARE(o->property("test3_1").toBool(), true);
3892 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3893 QObject *o = component.create();
3896 QCOMPARE(o->property("test1").toBool(), true);
3897 QCOMPARE(o->property("test2").toBool(), true);
3898 QCOMPARE(o->property("test3").toBool(), true);
3899 QCOMPARE(o->property("test4").toBool(), true);
3900 QCOMPARE(o->property("test5").toBool(), true);
3901 QCOMPARE(o->property("test6").toBool(), true);
3906 // Including file with ".pragma library"
3908 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3909 QObject *o = component.create();
3911 QCOMPARE(o->property("test1").toInt(), 100);
3918 TestHTTPServer server(8111);
3919 QVERIFY(server.isValid());
3920 server.serveDirectory(SRCDIR "/data");
3922 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3923 QObject *o = component.create();
3926 QTRY_VERIFY(o->property("done").toBool() == true);
3927 QTRY_VERIFY(o->property("done2").toBool() == true);
3929 QCOMPARE(o->property("test1").toBool(), true);
3930 QCOMPARE(o->property("test2").toBool(), true);
3931 QCOMPARE(o->property("test3").toBool(), true);
3932 QCOMPARE(o->property("test4").toBool(), true);
3933 QCOMPARE(o->property("test5").toBool(), true);
3935 QCOMPARE(o->property("test6").toBool(), true);
3936 QCOMPARE(o->property("test7").toBool(), true);
3937 QCOMPARE(o->property("test8").toBool(), true);
3938 QCOMPARE(o->property("test9").toBool(), true);
3939 QCOMPARE(o->property("test10").toBool(), true);
3946 TestHTTPServer server(8111);
3947 QVERIFY(server.isValid());
3948 server.serveDirectory(SRCDIR "/data");
3950 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3951 QObject *o = component.create();
3954 QTRY_VERIFY(o->property("done").toBool() == true);
3956 QCOMPARE(o->property("test1").toBool(), true);
3957 QCOMPARE(o->property("test2").toBool(), true);
3958 QCOMPARE(o->property("test3").toBool(), true);
3964 void tst_qdeclarativeecmascript::signalHandlers()
3966 QDeclarativeComponent component(&engine, TEST_FILE("signalHandlers.qml"));
3967 QObject *o = component.create();
3970 QVERIFY(o->property("count").toInt() == 0);
3971 QMetaObject::invokeMethod(o, "testSignalCall");
3972 QCOMPARE(o->property("count").toInt(), 1);
3974 QMetaObject::invokeMethod(o, "testSignalHandlerCall");
3975 QCOMPARE(o->property("count").toInt(), 1);
3976 QCOMPARE(o->property("errorString").toString(), QLatin1String("TypeError: Property 'onTestSignal' of object [object Object] is not a function"));
3978 QVERIFY(o->property("funcCount").toInt() == 0);
3979 QMetaObject::invokeMethod(o, "testSignalConnection");
3980 QCOMPARE(o->property("funcCount").toInt(), 1);
3982 QMetaObject::invokeMethod(o, "testSignalHandlerConnection");
3983 QCOMPARE(o->property("funcCount").toInt(), 2);
3985 QMetaObject::invokeMethod(o, "testSignalDefined");
3986 QCOMPARE(o->property("definedResult").toBool(), true);
3988 QMetaObject::invokeMethod(o, "testSignalHandlerDefined");
3989 QCOMPARE(o->property("definedHandlerResult").toBool(), true);
3994 void tst_qdeclarativeecmascript::qtbug_10696()
3996 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3997 QObject *o = component.create();
4002 void tst_qdeclarativeecmascript::qtbug_11606()
4004 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
4005 QObject *o = component.create();
4007 QCOMPARE(o->property("test").toBool(), true);
4011 void tst_qdeclarativeecmascript::qtbug_11600()
4013 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
4014 QObject *o = component.create();
4016 QCOMPARE(o->property("test").toBool(), true);
4020 // Reading and writing non-scriptable properties should fail
4021 void tst_qdeclarativeecmascript::nonscriptable()
4023 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
4024 QObject *o = component.create();
4026 QCOMPARE(o->property("readOk").toBool(), true);
4027 QCOMPARE(o->property("writeOk").toBool(), true);
4031 // deleteLater() should not be callable from QML
4032 void tst_qdeclarativeecmascript::deleteLater()
4034 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
4035 QObject *o = component.create();
4037 QCOMPARE(o->property("test").toBool(), true);
4041 void tst_qdeclarativeecmascript::in()
4043 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
4044 QObject *o = component.create();
4046 QCOMPARE(o->property("test1").toBool(), true);
4047 QCOMPARE(o->property("test2").toBool(), true);
4051 void tst_qdeclarativeecmascript::sharedAttachedObject()
4053 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
4054 QObject *o = component.create();
4056 QCOMPARE(o->property("test1").toBool(), true);
4057 QCOMPARE(o->property("test2").toBool(), true);
4062 void tst_qdeclarativeecmascript::objectName()
4064 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
4065 QObject *o = component.create();
4068 QCOMPARE(o->property("test1").toString(), QString("hello"));
4069 QCOMPARE(o->property("test2").toString(), QString("ell"));
4071 o->setObjectName("world");
4073 QCOMPARE(o->property("test1").toString(), QString("world"));
4074 QCOMPARE(o->property("test2").toString(), QString("orl"));
4079 void tst_qdeclarativeecmascript::writeRemovesBinding()
4081 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
4082 QObject *o = component.create();
4085 QCOMPARE(o->property("test").toBool(), true);
4090 // Test bindings assigned to alias properties actually assign to the alias' target
4091 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
4093 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
4094 QObject *o = component.create();
4097 QCOMPARE(o->property("test").toBool(), true);
4102 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
4103 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
4106 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
4107 QObject *o = component.create();
4110 QCOMPARE(o->property("test").toBool(), true);
4116 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
4117 QObject *o = component.create();
4120 QCOMPARE(o->property("test").toBool(), true);
4126 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
4127 QObject *o = component.create();
4130 QCOMPARE(o->property("test").toBool(), true);
4136 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
4137 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
4140 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
4141 QObject *o = component.create();
4144 QCOMPARE(o->property("test").toBool(), true);
4150 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
4151 QObject *o = component.create();
4154 QCOMPARE(o->property("test").toBool(), true);
4160 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
4161 QObject *o = component.create();
4164 QCOMPARE(o->property("test").toBool(), true);
4170 // Allow an alais to a composite element
4172 void tst_qdeclarativeecmascript::aliasToCompositeElement()
4174 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
4176 QObject *object = component.create();
4177 QVERIFY(object != 0);
4182 void tst_qdeclarativeecmascript::revisionErrors()
4185 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
4186 QString url = component.url().toString();
4188 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
4189 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
4190 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
4192 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
4193 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
4194 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
4195 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4196 QVERIFY(object != 0);
4200 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
4201 QString url = component.url().toString();
4203 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
4204 // method2, prop2 from MyRevisionedClass not available
4205 // method4, prop4 from MyRevisionedSubclass not available
4206 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
4207 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
4208 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
4209 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
4210 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
4212 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
4213 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
4214 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
4215 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
4216 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
4217 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4218 QVERIFY(object != 0);
4222 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
4223 QString url = component.url().toString();
4225 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
4226 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
4227 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
4228 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
4229 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
4230 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
4231 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
4232 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
4233 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4234 QVERIFY(object != 0);
4239 void tst_qdeclarativeecmascript::revision()
4242 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
4243 QString url = component.url().toString();
4245 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4246 QVERIFY(object != 0);
4250 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
4251 QString url = component.url().toString();
4253 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4254 QVERIFY(object != 0);
4258 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
4259 QString url = component.url().toString();
4261 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
4262 QVERIFY(object != 0);
4265 // Test that non-root classes can resolve revisioned methods
4267 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
4269 QObject *object = component.create();
4270 QVERIFY(object != 0);
4271 QCOMPARE(object->property("test").toReal(), 11.);
4276 void tst_qdeclarativeecmascript::realToInt()
4278 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
4279 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
4280 QVERIFY(object != 0);
4282 QMetaObject::invokeMethod(object, "test1");
4283 QCOMPARE(object->value(), int(4));
4284 QMetaObject::invokeMethod(object, "test2");
4285 QCOMPARE(object->value(), int(8));
4287 void tst_qdeclarativeecmascript::dynamicString()
4289 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
4290 QObject *object = component.create();
4291 QVERIFY(object != 0);
4292 QCOMPARE(object->property("stringProperty").toString(),
4293 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
4296 void tst_qdeclarativeecmascript::automaticSemicolon()
4298 QDeclarativeComponent component(&engine, TEST_FILE("automaticSemicolon.qml"));
4299 QObject *object = component.create();
4300 QVERIFY(object != 0);
4303 QTEST_MAIN(tst_qdeclarativeecmascript)
4305 #include "tst_qdeclarativeecmascript.moc"