Test metatype registration errors with non-metatypes.
[profile/ivi/qtdeclarative.git] / tests / auto / qml / qqmlecmascript / tst_qqmlecmascript.cpp
index 40bff34..96c0ec1 100644 (file)
@@ -79,6 +79,7 @@ private slots:
     void boolPropertiesEvaluateAsBool();
     void methods();
     void signalAssignment();
+    void signalArguments();
     void bindingLoop();
     void basicExpressions();
     void basicExpressions_data();
@@ -150,8 +151,12 @@ private slots:
     void signalWithJSValueInVariant_twoEngines();
     void signalWithQJSValue_data();
     void signalWithQJSValue();
-    void moduleApi_data();
-    void moduleApi();
+    void singletonType_data();
+    void singletonType();
+    void singletonTypeCaching_data();
+    void singletonTypeCaching();
+    void singletonTypeImportOrder();
+    void singletonTypeResolution();
     void importScripts_data();
     void importScripts();
     void scarceResources();
@@ -160,6 +165,8 @@ private slots:
     void propertyChangeSlots();
     void propertyVar_data();
     void propertyVar();
+    void propertyQJSValue_data();
+    void propertyQJSValue();
     void propertyVarCpp();
     void propertyVarOwnership();
     void propertyVarImplicitOwnership();
@@ -184,11 +191,15 @@ private slots:
     void sequenceConversionBindings();
     void sequenceConversionCopy();
     void assignSequenceTypes();
+    void sequenceSort_data();
+    void sequenceSort();
     void qtbug_22464();
     void qtbug_21580();
     void singleV8BindingDestroyedDuringEvaluation();
     void bug1();
+#ifndef QT_NO_WIDGETS
     void bug2();
+#endif
     void dynamicCreationCrash();
     void dynamicCreationOwnership();
     void regExpBug();
@@ -241,6 +252,7 @@ private slots:
     void callQtInvokables();
     void invokableObjectArg();
     void invokableObjectRet();
+    void invokableEnumRet();
     void qtbug_20344();
     void qtbug_22679();
     void qtbug_22843_data();
@@ -263,6 +275,14 @@ private slots:
     void bindingSuppression();
     void signalEmitted();
     void threadSignal();
+    void qqmldataDestroyed();
+    void secondAlias();
+    void varAlias();
+    void overrideDataAssert();
+    void fallbackBindings_data();
+    void fallbackBindings();
+    void propertyOverride();
+    void concatenatedStringPropertyAccess();
 
 private:
     static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -286,6 +306,7 @@ void tst_qqmlecmascript::assignBasicTypes()
     QVERIFY(object != 0);
     QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
     QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
+    QCOMPARE(object->relatedEnumProperty(), MyEnumContainer::RelatedValue);
     QCOMPARE(object->stringProperty(), QString("Hello World!"));
     QCOMPARE(object->uintProperty(), uint(10));
     QCOMPARE(object->intProperty(), -19);
@@ -314,6 +335,7 @@ void tst_qqmlecmascript::assignBasicTypes()
     QVERIFY(object != 0);
     QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
     QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
+    QCOMPARE(object->relatedEnumProperty(), MyEnumContainer::RelatedValue);
     QCOMPARE(object->stringProperty(), QString("Hello World!"));
     QCOMPARE(object->uintProperty(), uint(10));
     QCOMPARE(object->intProperty(), -19);
@@ -492,22 +514,42 @@ void tst_qqmlecmascript::signalAssignment()
 
     {
         QQmlComponent component(&engine, testFileUrl("signalAssignment.3.qml"));
+        QVERIFY(component.isError());
+        QString expectedErrorString = component.url().toString() + QLatin1String(":4 Signal uses unnamed parameter followed by named parameter.\n");
+        QCOMPARE(component.errorString(), expectedErrorString);
+    }
+
+    {
+        QQmlComponent component(&engine, testFileUrl("signalAssignment.4.qml"));
+        QVERIFY(component.isError());
+        QString expectedErrorString = component.url().toString() + QLatin1String(":5 Signal parameter \"parseInt\" hides global variable.\n");
+        QCOMPARE(component.errorString(), expectedErrorString);
+    }
+}
+
+void tst_qqmlecmascript::signalArguments()
+{
+    {
+        QQmlComponent component(&engine, testFileUrl("signalArguments.1.qml"));
         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
         QVERIFY(object != 0);
         QCOMPARE(object->string(), QString());
-        emit object->unnamedArgumentSignal(19, 10.25, "Hello world!");
-        QEXPECT_FAIL("", "QTBUG-24481", Continue);
-        QCOMPARE(object->string(), QString("pass 19 Hello world!"));
+        emit object->basicSignal();
+        QCOMPARE(object->string(), QString("pass"));
+        QCOMPARE(object->property("argumentCount").toInt(), 0);
+        QCOMPARE(object->property("calleeCorrect").toBool(), true);
         delete object;
     }
 
     {
-        QQmlComponent component(&engine, testFileUrl("signalAssignment.4.qml"));
+        QQmlComponent component(&engine, testFileUrl("signalArguments.2.qml"));
         MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
         QVERIFY(object != 0);
         QCOMPARE(object->string(), QString());
-        emit object->signalWithGlobalName(19);
-        QCOMPARE(object->string(), QString("pass 5"));
+        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
+        QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
+        QCOMPARE(object->property("argumentCount").toInt(), 5);
+        QCOMPARE(object->property("calleeCorrect").toBool(), true);
         delete object;
     }
 }
@@ -647,13 +689,13 @@ void tst_qqmlecmascript::arrayExpressions()
 
     MyExpression expr(&context, "[a, b, c, 10]");
     QVariant result = expr.evaluate();
-    QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
-    QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
+    QCOMPARE(result.userType(), qMetaTypeId<QVariantList>());
+    QVariantList list = qvariant_cast<QVariantList>(result);
     QCOMPARE(list.count(), 4);
-    QCOMPARE(list.at(0), &obj1);
-    QCOMPARE(list.at(1), &obj2);
-    QCOMPARE(list.at(2), &obj3);
-    QCOMPARE(list.at(3), (QObject *)0);
+    QCOMPARE(list.at(0).value<QObject*>(), &obj1);
+    QCOMPARE(list.at(1).value<QObject*>(), &obj2);
+    QCOMPARE(list.at(2).value<QObject*>(), &obj3);
+    QCOMPARE(list.at(3).value<int>(), 10);
 }
 
 // Tests that modifying a context property will reevaluate expressions
@@ -901,6 +943,10 @@ void tst_qqmlecmascript::enums()
     QObject *object = component.create();
     QVERIFY(object != 0);
 
+    QCOMPARE(object->property("enumProperty").toInt(), (int)MyQmlObject::EnumValue2);
+    QCOMPARE(object->property("relatedEnumProperty").toInt(), (int)MyEnumContainer::RelatedValue);
+    QCOMPARE(object->property("unrelatedEnumProperty").toInt(), (int)MyEnumContainer::RelatedValue);
+    QCOMPARE(object->property("qtEnumProperty").toInt(), (int)Qt::CaseInsensitive);
     QCOMPARE(object->property("a").toInt(), 0);
     QCOMPARE(object->property("b").toInt(), 1);
     QCOMPARE(object->property("c").toInt(), 2);
@@ -911,22 +957,53 @@ void tst_qqmlecmascript::enums()
     QCOMPARE(object->property("h").toInt(), 3);
     QCOMPARE(object->property("i").toInt(), 19);
     QCOMPARE(object->property("j").toInt(), 19);
+    QCOMPARE(object->property("k").toInt(), 42);
+    QCOMPARE(object->property("l").toInt(), 333);
 
     delete object;
     }
     // Non-existent enums
     {
-    QQmlComponent component(&engine, testFileUrl("enums.2.qml"));
-
-    QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int";
-    QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int";
-    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
-    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+    QUrl file = testFileUrl("enums.2.qml");
+    QString w1 = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'MyEnum' for property 'MyUnregisteredEnumTypeObject::enumProperty'");
+    QString w2 = QLatin1String("QQmlExpression: Expression ") + testFileUrl("enums.2.qml").toString() + QLatin1String(":9 depends on non-NOTIFYable properties:");
+    QString w3 = QLatin1String("    MyUnregisteredEnumTypeObject::enumProperty");
+    QString w4 = file.toString() + ":7: Unable to assign [undefined] to int";
+    QString w5 = file.toString() + ":8: Unable to assign [undefined] to int";
+    QString w6 = file.toString() + ":9: Unable to assign [undefined] to int";
+    QString w7 = file.toString() + ":13: Unable to assign [undefined] to [unknown property type]";
+    QString w8 = file.toString() + ":31: Unable to assign int to [unknown property type]";
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w1));
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w2));
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w3));
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w4));
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w5));
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w6));
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w7));
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w8));
 
+    QQmlComponent component(&engine, testFileUrl("enums.2.qml"));
     QObject *object = component.create();
     QVERIFY(object != 0);
     QCOMPARE(object->property("a").toInt(), 0);
     QCOMPARE(object->property("b").toInt(), 0);
+    QCOMPARE(object->property("c").toInt(), 0);
+
+    QString w9 = file.toString() + ":18: Error: Cannot assign JavaScript function to [unknown property type]";
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w9));
+    QMetaObject::invokeMethod(object, "testAssignmentOne");
+
+    QString w10 = file.toString() + ":21: Error: Cannot assign [undefined] to [unknown property type]";
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w10));
+    QMetaObject::invokeMethod(object, "testAssignmentTwo");
+
+    QString w11 = file.toString() + ":24: Error: Cannot assign [undefined] to [unknown property type]";
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w11));
+    QMetaObject::invokeMethod(object, "testAssignmentThree");
+
+    QString w12 = file.toString() + ":34: Error: Cannot assign int to an unregistered type";
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(w12));
+    QMetaObject::invokeMethod(object, "testAssignmentFour");
 
     delete object;
     }
@@ -945,6 +1022,8 @@ void tst_qqmlecmascript::enums()
     QCOMPARE(object->property("f").toInt(), 3);
     QCOMPARE(object->property("h").toInt(), 2);
     QCOMPARE(object->property("i").toInt(), 3);
+    QCOMPARE(object->property("j").toInt(), -1);
+    QCOMPARE(object->property("k").toInt(), 42);
 
     // count of change signals
     QCOMPARE(object->property("ac").toInt(), 0);
@@ -955,6 +1034,8 @@ void tst_qqmlecmascript::enums()
     QCOMPARE(object->property("fc").toInt(), 0);
     QCOMPARE(object->property("hc").toInt(), 1); // namespace -> binding
     QCOMPARE(object->property("ic").toInt(), 1); // namespace -> binding
+    QCOMPARE(object->property("jc").toInt(), 0);
+    QCOMPARE(object->property("kc").toInt(), 0);
 
     delete object;
     }
@@ -1408,12 +1489,9 @@ void tst_qqmlecmascript::componentCreation()
         QVERIFY(created);
 
         QObject *expectedParent;
-        if (createdParent.isEmpty()) {
-            // For now, the parent should be the engine; this will change for QTBUG-24841
-            expectedParent = &engine;
-        } else if (createdParent == QLatin1String("obj")) {
+        if (createdParent == QLatin1String("obj")) {
             expectedParent = object;
-        } else if (createdParent == QLatin1String("null")) {
+        } else if ((createdParent == QLatin1String("null")) || createdParent.isEmpty()) {
             expectedParent = 0;
         }
         QCOMPARE(created->parent(), expectedParent);
@@ -1582,15 +1660,15 @@ void tst_qqmlecmascript::objectHasOwnProperty()
     QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
     QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
     QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
-    QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
-    QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
+    QCOMPARE(child->property("singletonTypeTypeHasOwnProperty").toBool(), true);
+    QCOMPARE(child->property("singletonTypePropertyTypeHasOwnProperty").toBool(), true);
 
     QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
     QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
     QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
     QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
     QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
-    QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
+    QCOMPARE(child->property("singletonTypeNonPropertyHasOwnProperty").toBool(), false);
     QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
     QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
     QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
@@ -2010,6 +2088,7 @@ void tst_qqmlecmascript::bug1()
     delete object;
 }
 
+#ifndef QT_NO_WIDGETS
 void tst_qqmlecmascript::bug2()
 {
     QQmlComponent component(&engine);
@@ -2020,6 +2099,7 @@ void tst_qqmlecmascript::bug2()
 
     delete object;
 }
+#endif
 
 // Don't crash in createObject when the component has errors.
 void tst_qqmlecmascript::dynamicCreationCrash()
@@ -2159,7 +2239,9 @@ static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::O
 
 void tst_qqmlecmascript::callQtInvokables()
 {
-    MyInvokableObject o;
+    // This object has JS ownership, as the call to method_NoArgs_QObject() in this test will return
+    // it, which will set the indestructible flag to false.
+    MyInvokableObject *o = new MyInvokableObject();
 
     QQmlEngine qmlengine;
     QQmlEnginePrivate *ep = QQmlEnginePrivate::get(&qmlengine);
@@ -2169,542 +2251,548 @@ void tst_qqmlecmascript::callQtInvokables()
     v8::HandleScope handle_scope;
     v8::Context::Scope scope(engine->context());
 
-    v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
+    v8::Local<v8::Object> object = engine->newQObject(o)->ToObject();
 
     // Non-existent methods
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), -1);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), -1);
+    QCOMPARE(o->actuals().count(), 0);
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), -1);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), -1);
+    QCOMPARE(o->actuals().count(), 0);
 
     // Insufficient arguments
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_ERROR("object.method_int()"));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), -1);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), -1);
+    QCOMPARE(o->actuals().count(), 0);
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), -1);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), -1);
+    QCOMPARE(o->actuals().count(), 0);
 
     // Excessive arguments
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 8);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(10));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 8);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(10));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 9);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(10));
-    QCOMPARE(o.actuals().at(1), QVariant(11));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 9);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(10));
+    QCOMPARE(o->actuals().at(1), QVariant(11));
 
     // Test return types
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 0);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 0);
+    QCOMPARE(o->actuals().count(), 0);
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 1);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 1);
+    QCOMPARE(o->actuals().count(), 0);
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 2);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 2);
+    QCOMPARE(o->actuals().count(), 0);
 
-    o.reset();
+    o->reset();
     {
     v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
     QVERIFY(!ret.IsEmpty());
     QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 3);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 3);
+    QCOMPARE(o->actuals().count(), 0);
     }
 
-    o.reset();
+    o->reset();
     {
     v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
-    QCOMPARE(engine->toQObject(ret), (QObject *)&o);
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 4);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(engine->toQObject(ret), (QObject *)o);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 4);
+    QCOMPARE(o->actuals().count(), 0);
     }
 
-    o.reset();
-    QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 5);
-    QCOMPARE(o.actuals().count(), 0);
+    o->reset();
+    QVERIFY(EVALUATE_ERROR("object.method_NoArgs_unknown()"));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), -1);
+    QCOMPARE(o->actuals().count(), 0);
 
-    o.reset();
+    o->reset();
     {
     v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
     QVERIFY(ret->IsString());
     QCOMPARE(engine->toString(ret), QString("Hello world"));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 6);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 6);
+    QCOMPARE(o->actuals().count(), 0);
     }
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 7);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 7);
+    QCOMPARE(o->actuals().count(), 0);
 
     // Test arg types
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 8);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(94));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 8);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(94));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 8);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(94));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 8);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(94));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 8);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 8);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 8);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 8);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 8);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 8);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 8);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 8);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 9);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(122));
-    QCOMPARE(o.actuals().at(1), QVariant(9));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 9);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(122));
+    QCOMPARE(o->actuals().at(1), QVariant(9));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 10);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(94.3));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 10);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(94.3));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 10);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(94.3));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 10);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(94.3));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 10);
-    QCOMPARE(o.actuals().count(), 1);
-    QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 10);
+    QCOMPARE(o->actuals().count(), 1);
+    QVERIFY(qIsNaN(o->actuals().at(0).toDouble()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 10);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 10);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 10);
-    QCOMPARE(o.actuals().count(), 1);
-    QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 10);
+    QCOMPARE(o->actuals().count(), 1);
+    QVERIFY(qIsNaN(o->actuals().at(0).toDouble()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 10);
-    QCOMPARE(o.actuals().count(), 1);
-    QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 10);
+    QCOMPARE(o->actuals().count(), 1);
+    QVERIFY(qIsNaN(o->actuals().at(0).toDouble()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 11);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 11);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant("Hello world"));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 11);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant("19"));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 11);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant("19"));
 
-    o.reset();
+    o->reset();
     {
-    QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
+    QString expected = "MyInvokableObject(0x" + QString::number((quintptr)o, 16) + ")";
     QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 11);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(expected));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 11);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(expected));
     }
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 11);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QString()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 11);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QString()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 11);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QString()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 11);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QString()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 12);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 12);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QPointF()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 12);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 12);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QPointF()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 12);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 12);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QPointF()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 12);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 12);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QPointF()));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 12);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 12);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QPointF(99.3, -10.2)));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 12);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 12);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QPointF(9, 12)));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 13);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 13);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), qVariantFromValue((QObject *)0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 13);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 13);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), qVariantFromValue((QObject *)0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 13);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 13);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), qVariantFromValue((QObject *)0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 13);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 13);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), qVariantFromValue((QObject *)0));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 13);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 13);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), qVariantFromValue((QObject *)o));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 14);
-    QCOMPARE(o.actuals().count(), 1);
-    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 14);
+    QCOMPARE(o->actuals().count(), 1);
+    QVERIFY(qvariant_cast<QJSValue>(o->actuals().at(0)).isNull());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 14);
-    QCOMPARE(o.actuals().count(), 1);
-    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 14);
+    QCOMPARE(o->actuals().count(), 1);
+    QVERIFY(qvariant_cast<QJSValue>(o->actuals().at(0)).isUndefined());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 14);
-    QCOMPARE(o.actuals().count(), 1);
-    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 14);
+    QCOMPARE(o->actuals().count(), 1);
+    QVERIFY(qvariant_cast<QJSValue>(o->actuals().at(0)).strictlyEquals(QJSValue(19)));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 14);
-    QCOMPARE(o.actuals().count(), 1);
-    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 14);
+    QCOMPARE(o->actuals().count(), 1);
+    QVERIFY(qvariant_cast<QJSValue>(o->actuals().at(0)).isArray());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 15);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(4));
-    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 15);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(4));
+    QVERIFY(qvariant_cast<QJSValue>(o->actuals().at(1)).isNull());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 15);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(8));
-    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 15);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(8));
+    QVERIFY(qvariant_cast<QJSValue>(o->actuals().at(1)).isUndefined());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 15);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(3));
-    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 15);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(3));
+    QVERIFY(qvariant_cast<QJSValue>(o->actuals().at(1)).strictlyEquals(QJSValue(19)));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 15);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(44));
-    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 15);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(44));
+    QVERIFY(qvariant_cast<QJSValue>(o->actuals().at(1)).isArray());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_ERROR("object.method_overload()"));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), -1);
-    QCOMPARE(o.actuals().count(), 0);
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), -1);
+    QCOMPARE(o->actuals().count(), 0);
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 16);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(10));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 16);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(10));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 17);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(10));
-    QCOMPARE(o.actuals().at(1), QVariant(11));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 17);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(10));
+    QCOMPARE(o->actuals().at(1), QVariant(11));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 18);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 18);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(QString("Hello")));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 19);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(9));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 19);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(9));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 20);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(10));
-    QCOMPARE(o.actuals().at(1), QVariant(19));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 20);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(10));
+    QCOMPARE(o->actuals().at(1), QVariant(19));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 20);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(10));
-    QCOMPARE(o.actuals().at(1), QVariant(13));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 20);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(10));
+    QCOMPARE(o->actuals().at(1), QVariant(13));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), -3);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(o.actuals().at(0), QVariant(9));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), -3);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(o->actuals().at(0), QVariant(9));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 21);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(9));
-    QCOMPARE(o.actuals().at(1), QVariant());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 21);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(9));
+    QCOMPARE(o->actuals().at(1), QVariant());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 21);
-    QCOMPARE(o.actuals().count(), 2);
-    QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
-    QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 21);
+    QCOMPARE(o->actuals().count(), 2);
+    QCOMPARE(o->actuals().at(0), QVariant(QString("Hello")));
+    QCOMPARE(o->actuals().at(1), QVariant(QString("World")));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonObject({foo:123})", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 22);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonObject>(o.actuals().at(0)), QJsonDocument::fromJson("{\"foo\":123}").object());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 22);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonObject>(o->actuals().at(0)), QJsonDocument::fromJson("{\"foo\":123}").object());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonArray([123])", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 23);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonArray>(o.actuals().at(0)), QJsonDocument::fromJson("[123]").array());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 23);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonArray>(o->actuals().at(0)), QJsonDocument::fromJson("[123]").array());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonValue(123)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 24);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(123));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 24);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(123));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonValue(42.35)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 24);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(42.35));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 24);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(42.35));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonValue('ciao')", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 24);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(QStringLiteral("ciao")));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 24);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(QStringLiteral("ciao")));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonValue(true)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 24);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(true));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 24);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(true));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonValue(false)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 24);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(false));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 24);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(false));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonValue(null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 24);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(QJsonValue::Null));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 24);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(QJsonValue::Null));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_QJsonValue(undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 24);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(QJsonValue::Undefined));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 24);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(QJsonValue::Undefined));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_overload({foo:123})", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 25);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonObject>(o.actuals().at(0)), QJsonDocument::fromJson("{\"foo\":123}").object());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 25);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonObject>(o->actuals().at(0)), QJsonDocument::fromJson("{\"foo\":123}").object());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_overload([123])", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 26);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonArray>(o.actuals().at(0)), QJsonDocument::fromJson("[123]").array());
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 26);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonArray>(o->actuals().at(0)), QJsonDocument::fromJson("[123]").array());
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_overload(null)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 27);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(QJsonValue::Null));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 27);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(QJsonValue::Null));
 
-    o.reset();
+    o->reset();
     QVERIFY(EVALUATE_VALUE("object.method_overload(undefined)", v8::Undefined()));
-    QCOMPARE(o.error(), false);
-    QCOMPARE(o.invoked(), 27);
-    QCOMPARE(o.actuals().count(), 1);
-    QCOMPARE(qvariant_cast<QJsonValue>(o.actuals().at(0)), QJsonValue(QJsonValue::Undefined));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), 27);
+    QCOMPARE(o->actuals().count(), 1);
+    QCOMPARE(qvariant_cast<QJsonValue>(o->actuals().at(0)), QJsonValue(QJsonValue::Undefined));
+
+    o->reset();
+    QVERIFY(EVALUATE_ERROR("object.method_unknown(null)"));
+    QCOMPARE(o->error(), false);
+    QCOMPARE(o->invoked(), -1);
+    QCOMPARE(o->actuals().count(), 0);
 }
 
 // QTBUG-13047 (check that you can pass registered object types as args)
@@ -2732,6 +2820,16 @@ void tst_qqmlecmascript::invokableObjectRet()
     delete o;
 }
 
+void tst_qqmlecmascript::invokableEnumRet()
+{
+    QQmlComponent component(&engine, testFileUrl("invokableEnumRet.qml"));
+
+    QObject *o = component.create();
+    QVERIFY(o);
+    QCOMPARE(o->property("test").toBool(), true);
+    delete o;
+}
+
 // QTBUG-5675
 void tst_qqmlecmascript::listToVariant()
 {
@@ -3358,6 +3456,11 @@ void tst_qqmlecmascript::signalWithUnknownTypes()
 
     QCOMPARE(result.value, type.value);
 
+    MyQmlObject::MyOtherType othertype;
+    othertype.value = 17;
+    emit object->signalWithCompletelyUnknownType(othertype);
+
+    QVERIFY(!object->variant().isValid());
 
     delete object;
 }
@@ -3459,7 +3562,7 @@ void tst_qqmlecmascript::signalWithQJSValue()
     QVERIFY(object->qjsvalue().strictlyEquals(value));
 }
 
-void tst_qqmlecmascript::moduleApi_data()
+void tst_qqmlecmascript::singletonType_data()
 {
     QTest::addColumn<QUrl>("testfile");
     QTest::addColumn<QString>("errorMessage");
@@ -3471,20 +3574,19 @@ void tst_qqmlecmascript::moduleApi_data()
     QTest::addColumn<QStringList>("readBackProperties");
     QTest::addColumn<QVariantList>("readBackExpectedValues");
 
-    QTest::newRow("qobject, register + read + method")
-            << testFileUrl("moduleapi/qobjectModuleApi.qml")
+    QTest::newRow("qobject, register + read + method [no qualifier]")
+            << testFileUrl("singletontype/qobjectSingletonTypeNoQualifier.qml")
             << QString()
             << QStringList()
-            << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest"
-                   << "qobjectMinorVersionTest" << "qobjectMajorVersionTest" << "qobjectParentedTest")
-            << (QVariantList() << 20 << 20 << 1 << 20 << 20 << 26)
+            << (QStringList() << "qobjectPropertyTest" << "qobjectMethodTest")
+            << (QVariantList() << 20 << 1)
             << QStringList()
             << QVariantList()
             << QStringList()
             << QVariantList();
 
-    QTest::newRow("script, register + read")
-            << testFileUrl("moduleapi/scriptModuleApi.qml")
+    QTest::newRow("script, register + read [no qualifier]")
+            << testFileUrl("singletontype/scriptSingletonTypeNoQualifier.qml")
             << QString()
             << QStringList()
             << (QStringList() << "scriptTest")
@@ -3494,32 +3596,34 @@ void tst_qqmlecmascript::moduleApi_data()
             << QStringList()
             << QVariantList();
 
-    QTest::newRow("qobject, caching + read")
-            << testFileUrl("moduleapi/qobjectModuleApiCaching.qml")
+    QTest::newRow("qobject, register + read + method")
+            << testFileUrl("singletontype/qobjectSingletonType.qml")
             << QString()
             << QStringList()
-            << (QStringList() << "existingUriTest" << "qobjectParentedTest")
-            << (QVariantList() << 20 << 26) // 26, shouldn't have incremented to 27.
+            << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest"
+                   << "qobjectMinorVersionMethodTest" << "qobjectMinorVersionTest"
+                   << "qobjectMajorVersionTest" << "qobjectParentedTest")
+            << (QVariantList() << 20 << 20 << 2 << 1 << 20 << 20 << 26)
             << QStringList()
             << QVariantList()
             << QStringList()
             << QVariantList();
 
-    QTest::newRow("script, caching + read")
-            << testFileUrl("moduleapi/scriptModuleApiCaching.qml")
+    QTest::newRow("script, register + read")
+            << testFileUrl("singletontype/scriptSingletonType.qml")
             << QString()
             << QStringList()
             << (QStringList() << "scriptTest")
-            << (QVariantList() << 13) // 13, shouldn't have incremented to 14.
+            << (QVariantList() << 14) // will have incremented, since we create a new engine each row in this test.
             << QStringList()
             << QVariantList()
             << QStringList()
             << QVariantList();
 
     QTest::newRow("qobject, writing + readonly constraints")
-            << testFileUrl("moduleapi/qobjectModuleApiWriting.qml")
+            << testFileUrl("singletontype/qobjectSingletonTypeWriting.qml")
             << QString()
-            << (QStringList() << QString(testFileUrl("moduleapi/qobjectModuleApiWriting.qml").toString() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"")))
+            << (QStringList() << QString(testFileUrl("singletontype/qobjectSingletonTypeWriting.qml").toString() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"")))
             << (QStringList() << "readOnlyProperty" << "writableProperty" << "writableFinalProperty")
             << (QVariantList() << 20 << 50 << 10)
             << (QStringList() << "firstProperty" << "secondProperty")
@@ -3528,18 +3632,18 @@ void tst_qqmlecmascript::moduleApi_data()
             << (QVariantList() << 20 << 30 << 30);
 
     QTest::newRow("script, writing + readonly constraints")
-            << testFileUrl("moduleapi/scriptModuleApiWriting.qml")
+            << testFileUrl("singletontype/scriptSingletonTypeWriting.qml")
             << QString()
-            << (QStringList() << QString(testFileUrl("moduleapi/scriptModuleApiWriting.qml").toString() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\"")))
+            << (QStringList() << QString(testFileUrl("singletontype/scriptSingletonTypeWriting.qml").toString() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\"")))
             << (QStringList() << "readBack" << "unchanged")
-            << (QVariantList() << 13 << 42)
+            << (QVariantList() << 15 << 42)
             << (QStringList() << "firstProperty" << "secondProperty")
             << (QVariantList() << 30 << 30)
             << (QStringList() << "readBack" << "unchanged")
             << (QVariantList() << 30 << 42);
 
-    QTest::newRow("qobject module API enum values in JS")
-            << testFileUrl("moduleapi/qobjectModuleApiEnums.qml")
+    QTest::newRow("qobject singleton Type enum values in JS")
+            << testFileUrl("singletontype/qobjectSingletonTypeEnums.qml")
             << QString()
             << QStringList()
             << (QStringList() << "enumValue" << "enumMethod")
@@ -3550,7 +3654,7 @@ void tst_qqmlecmascript::moduleApi_data()
             << QVariantList();
 
     QTest::newRow("qobject, invalid major version fail")
-            << testFileUrl("moduleapi/moduleApiMajorVersionFail.qml")
+            << testFileUrl("singletontype/singletonTypeMajorVersionFail.qml")
             << QString("QQmlComponent: Component is not ready")
             << QStringList()
             << QStringList()
@@ -3561,7 +3665,7 @@ void tst_qqmlecmascript::moduleApi_data()
             << QVariantList();
 
     QTest::newRow("qobject, invalid minor version fail")
-            << testFileUrl("moduleapi/moduleApiMinorVersionFail.qml")
+            << testFileUrl("singletontype/singletonTypeMinorVersionFail.qml")
             << QString("QQmlComponent: Component is not ready")
             << QStringList()
             << QStringList()
@@ -3571,19 +3675,19 @@ void tst_qqmlecmascript::moduleApi_data()
             << QStringList()
             << QVariantList();
 
-    QTest::newRow("legacy module api registration")
-            << testFileUrl("moduleapi/qobjectModuleApiLegacy.qml")
+    QTest::newRow("qobject, multiple in namespace")
+            << testFileUrl("singletontype/singletonTypeMultiple.qml")
             << QString()
-            << QStringList() // warning doesn't occur in the test, but in registerTypes()
-            << (QStringList() << "legacyModulePropertyTest" << "legacyModuleMethodTest")
-            << (QVariantList() << 20 << 2)
+            << QStringList()
+            << (QStringList() << "first" << "second")
+            << (QVariantList() << 35 << 42)
             << QStringList()
             << QVariantList()
             << QStringList()
             << QVariantList();
 }
 
-void tst_qqmlecmascript::moduleApi()
+void tst_qqmlecmascript::singletonType()
 {
     QFETCH(QUrl, testfile);
     QFETCH(QString, errorMessage);
@@ -3595,7 +3699,8 @@ void tst_qqmlecmascript::moduleApi()
     QFETCH(QStringList, readBackProperties);
     QFETCH(QVariantList, readBackExpectedValues);
 
-    QQmlComponent component(&engine, testfile);
+    QQmlEngine cleanEngine; // so tests don't interfere which each other, as singleton types are engine-singletons only.
+    QQmlComponent component(&cleanEngine, testfile);
 
     if (!errorMessage.isEmpty())
         QTest::ignoreMessage(QtWarningMsg, errorMessage.toLatin1().constData());
@@ -3619,6 +3724,63 @@ void tst_qqmlecmascript::moduleApi()
     }
 }
 
+void tst_qqmlecmascript::singletonTypeCaching_data()
+{
+    QTest::addColumn<QUrl>("testfile");
+    QTest::addColumn<QStringList>("readProperties");
+
+    QTest::newRow("qobject, caching + read")
+            << testFileUrl("singletontype/qobjectSingletonTypeCaching.qml")
+            << (QStringList() << "existingUriTest" << "qobjectParentedTest");
+
+    QTest::newRow("script, caching + read")
+            << testFileUrl("singletontype/scriptSingletonTypeCaching.qml")
+            << (QStringList() << "scriptTest");
+}
+
+void tst_qqmlecmascript::singletonTypeCaching()
+{
+    QFETCH(QUrl, testfile);
+    QFETCH(QStringList, readProperties);
+
+    // ensure that the singleton type instances are cached per-engine.
+
+    QQmlEngine cleanEngine;
+    QQmlComponent component(&cleanEngine, testfile);
+    QObject *object = component.create();
+    QVERIFY(object != 0);
+    QList<QVariant> firstValues;
+    QMetaObject::invokeMethod(object, "modifyValues");
+    for (int i = 0; i < readProperties.size(); ++i)
+        firstValues << object->property(readProperties.at(i).toLatin1().constData());
+    delete object;
+
+    QQmlComponent component2(&cleanEngine, testfile);
+    QObject *object2 = component2.create();
+    QVERIFY(object2 != 0);
+    for (int i = 0; i < readProperties.size(); ++i)
+        QCOMPARE(object2->property(readProperties.at(i).toLatin1().constData()), firstValues.at(i)); // cached, shouldn't have changed.
+    delete object2;
+}
+
+void tst_qqmlecmascript::singletonTypeImportOrder()
+{
+    QQmlComponent component(&engine, testFileUrl("singletontype/singletonTypeImportOrder.qml"));
+    QObject *object = component.create();
+    QVERIFY(object);
+    QVERIFY(object->property("v") == 1);
+    delete object;
+}
+
+void tst_qqmlecmascript::singletonTypeResolution()
+{
+    QQmlComponent component(&engine, testFileUrl("singletontype/singletonTypeResolution.qml"));
+    QObject *object = component.create();
+    QVERIFY(object);
+    QVERIFY(object->property("success") == true);
+    delete object;
+}
+
 void tst_qqmlecmascript::importScripts_data()
 {
     QTest::addColumn<QUrl>("testfile");
@@ -3710,8 +3872,8 @@ void tst_qqmlecmascript::importScripts_data()
             << (QStringList() << QLatin1String("testValue"))
             << (QVariantList() << QVariant(18));
 
-    QTest::newRow("import module api into js import")
-            << testFileUrl("jsimport/testImportModuleApi.qml")
+    QTest::newRow("import singleton type into js import")
+            << testFileUrl("jsimport/testImportSingletonType.qml")
             << QString()
             << QStringList()
             << (QStringList() << QLatin1String("testValue"))
@@ -3727,6 +3889,94 @@ void tst_qqmlecmascript::importScripts_data()
             << (QVariantList() << QVariant(QString("Hello"))
                                << QVariant(QString("Hello"))
                                << QVariant(QString("Hello")));
+
+    QTest::newRow("import module which exports a script which imports a remote module")
+            << testFileUrl("jsimport/testJsRemoteImport.qml")
+            << QString()
+            << QStringList()
+            << (QStringList() << QLatin1String("importedScriptStringValue")
+                              << QLatin1String("renamedScriptStringValue")
+                              << QLatin1String("reimportedScriptStringValue"))
+            << (QVariantList() << QVariant(QString("Hello"))
+                               << QVariant(QString("Hello"))
+                               << QVariant(QString("Hello")));
+
+    QTest::newRow("malformed import statement")
+            << testFileUrl("jsimportfail/malformedImport.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedImport.js").toString() + QLatin1String(":1: SyntaxError: Unexpected token ."))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed file name")
+            << testFileUrl("jsimportfail/malformedFile.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedFile.js").toString() + QLatin1String(":1:9: Imported file must be a script"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("missing file qualifier")
+            << testFileUrl("jsimportfail/missingFileQualifier.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/missingFileQualifier.js").toString() + QLatin1String(":1:1: File import requires a qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed file qualifier")
+            << testFileUrl("jsimportfail/malformedFileQualifier.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.js").toString() + QLatin1String(":1:20: File import requires a qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module qualifier 2")
+            << testFileUrl("jsimportfail/malformedFileQualifier.2.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.2.js").toString() + QLatin1String(":1:1: Invalid import qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module uri")
+            << testFileUrl("jsimportfail/malformedModule.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedModule.js").toString() + QLatin1String(":1:17: Invalid module URI"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("missing module version")
+            << testFileUrl("jsimportfail/missingModuleVersion.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/missingModuleVersion.js").toString() + QLatin1String(":1:17: Module import requires a version"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module version")
+            << testFileUrl("jsimportfail/malformedModuleVersion.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedModuleVersion.js").toString() + QLatin1String(":1:17: Module import requires a version"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("missing module qualifier")
+            << testFileUrl("jsimportfail/missingModuleQualifier.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/missingModuleQualifier.js").toString() + QLatin1String(":1:1: Module import requires a qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module qualifier")
+            << testFileUrl("jsimportfail/malformedModuleQualifier.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.js").toString() + QLatin1String(":1:21: Module import requires a qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module qualifier 2")
+            << testFileUrl("jsimportfail/malformedModuleQualifier.2.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.2.js").toString() + QLatin1String(":1:1: Invalid import qualifier"))
+            << QStringList()
+            << QVariantList();
 }
 
 void tst_qqmlecmascript::importScripts()
@@ -3737,6 +3987,15 @@ void tst_qqmlecmascript::importScripts()
     QFETCH(QStringList, propertyNames);
     QFETCH(QVariantList, propertyValues);
 
+    TestHTTPServer server(8111);
+    QVERIFY(server.isValid());
+    server.serveDirectory(dataDirectory() + "/remote");
+
+    QStringList importPathList = engine.importPathList();
+
+    QString remotePath(QLatin1String("http://127.0.0.1:8111/"));
+    engine.addImportPath(remotePath);
+
     QQmlComponent component(&engine, testfile);
 
     if (!errorMessage.isEmpty())
@@ -3746,6 +4005,8 @@ void tst_qqmlecmascript::importScripts()
         foreach (const QString &warning, warningMessages)
             QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 
+    QTRY_VERIFY(component.isReady());
+
     QObject *object = component.create();
     if (!errorMessage.isEmpty()) {
         QVERIFY(object == 0);
@@ -3755,6 +4016,8 @@ void tst_qqmlecmascript::importScripts()
             QCOMPARE(object->property(propertyNames.at(i).toLatin1().constData()), propertyValues.at(i));
         delete object;
     }
+
+    engine.setImportPathList(importPathList);
 }
 
 void tst_qqmlecmascript::scarceResources_other()
@@ -4226,6 +4489,7 @@ void tst_qqmlecmascript::propertyVar_data()
     QTest::newRow("declarative binding assignment") << testFileUrl("propertyVar.13.qml");
     QTest::newRow("imperative binding assignment") << testFileUrl("propertyVar.14.qml");
     QTest::newRow("stored binding assignment") << testFileUrl("propertyVar.15.qml");
+    QTest::newRow("function expression binding assignment") << testFileUrl("propertyVar.16.qml");
 }
 
 void tst_qqmlecmascript::propertyVar()
@@ -4241,6 +4505,45 @@ void tst_qqmlecmascript::propertyVar()
     delete object;
 }
 
+void tst_qqmlecmascript::propertyQJSValue_data()
+{
+    QTest::addColumn<QUrl>("qmlFile");
+
+    // valid
+    QTest::newRow("non-bindable object subproperty changed") << testFileUrl("propertyQJSValue.1.qml");
+    QTest::newRow("non-bindable object changed") << testFileUrl("propertyQJSValue.2.qml");
+    QTest::newRow("primitive changed") << testFileUrl("propertyQJSValue.3.qml");
+    QTest::newRow("javascript array modification") << testFileUrl("propertyQJSValue.4.qml");
+    QTest::newRow("javascript map modification") << testFileUrl("propertyQJSValue.5.qml");
+    QTest::newRow("javascript array assignment") << testFileUrl("propertyQJSValue.6.qml");
+    QTest::newRow("javascript map assignment") << testFileUrl("propertyQJSValue.7.qml");
+    QTest::newRow("literal property assignment") << testFileUrl("propertyQJSValue.8.qml");
+    QTest::newRow("qobject property assignment") << testFileUrl("propertyQJSValue.9.qml");
+    QTest::newRow("base class var property assignment") << testFileUrl("propertyQJSValue.10.qml");
+    QTest::newRow("javascript function assignment") << testFileUrl("propertyQJSValue.11.qml");
+    QTest::newRow("javascript special assignment") << testFileUrl("propertyQJSValue.12.qml");
+    QTest::newRow("declarative binding assignment") << testFileUrl("propertyQJSValue.13.qml");
+    QTest::newRow("imperative binding assignment") << testFileUrl("propertyQJSValue.14.qml");
+    QTest::newRow("stored binding assignment") << testFileUrl("propertyQJSValue.15.qml");
+    QTest::newRow("javascript function binding") << testFileUrl("propertyQJSValue.16.qml");
+
+    QTest::newRow("reset property") << testFileUrl("propertyQJSValue.reset.qml");
+    QTest::newRow("reset property in binding") << testFileUrl("propertyQJSValue.bindingreset.qml");
+}
+
+void tst_qqmlecmascript::propertyQJSValue()
+{
+    QFETCH(QUrl, qmlFile);
+
+    QQmlComponent component(&engine, qmlFile);
+    QObject *object = component.create();
+    QVERIFY(object != 0);
+
+    QCOMPARE(object->property("test").toBool(), true);
+
+    delete object;
+}
+
 // Tests that we can write QVariant values to var properties from C++
 void tst_qqmlecmascript::propertyVarCpp()
 {
@@ -4539,8 +4842,8 @@ void tst_qqmlecmascript::propertyVarInheritance()
     // we want to be able to track when the varProperties array of the last metaobject is disposed
     QObject *cco5 = object->property("varProperty").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>();
     QObject *ico5 = object->property("varProperty").value<QObject*>()->property("inheritanceVarProperty").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>();
-    QQmlVMEMetaObject *icovmemo = ((QQmlVMEMetaObject *)(ico5->metaObject()));
-    QQmlVMEMetaObject *ccovmemo = ((QQmlVMEMetaObject *)(cco5->metaObject()));
+    QQmlVMEMetaObject *icovmemo = QQmlVMEMetaObject::get(ico5);
+    QQmlVMEMetaObject *ccovmemo = QQmlVMEMetaObject::get(cco5);
     v8::Persistent<v8::Value> icoCanaryHandle;
     v8::Persistent<v8::Value> ccoCanaryHandle;
     {
@@ -4590,7 +4893,7 @@ void tst_qqmlecmascript::propertyVarInheritance2()
     {
         v8::HandleScope hs;
         propertyVarWeakRefCallbackCount = 0;                           // reset callback count.
-        childObjectVarArrayValueHandle = qPersistentNew(((QQmlVMEMetaObject *)(childObject->metaObject()))->vmeProperty(childObject->metaObject()->indexOfProperty("vp")));
+        childObjectVarArrayValueHandle = qPersistentNew(QQmlVMEMetaObject::get(childObject)->vmeProperty(childObject->metaObject()->indexOfProperty("vp")));
         childObjectVarArrayValueHandle.MakeWeak(&propertyVarWeakRefCallbackCount, propertyVarWeakRefCallback);
         gc(engine);
         QVERIFY(propertyVarWeakRefCallbackCount == 0);                 // should not have been collected yet.
@@ -4756,11 +5059,13 @@ void tst_qqmlecmascript::handleReferenceManagement()
         QVERIFY(second != 0);
         first->addReference(QQmlData::get(second)->v8object); // create circular reference
         second->addReference(QQmlData::get(first)->v8object); // note: must be weak.
-        // now we have to reparent and change ownership.
+        // now we have to reparent and change ownership, and unset the property references.
         first->setParent(0);
         second->setParent(0);
         QQmlEngine::setObjectOwnership(first, QQmlEngine::JavaScriptOwnership);
         QQmlEngine::setObjectOwnership(second, QQmlEngine::JavaScriptOwnership);
+        object->setProperty("first", QVariant::fromValue<QObject*>(0));
+        object->setProperty("second", QVariant::fromValue<QObject*>(0));
         gc(engine);
         QCOMPARE(dtorCount, 2); // despite circular references, both will be collected.
         delete object;
@@ -4849,7 +5154,7 @@ void tst_qqmlecmascript::handleReferenceManagement()
         second1->addReference(QQmlData::get(second2)->v8object); // create linear reference across engines
         second2->addReference(QQmlData::get(first2)->v8object);  // create linear reference within engine2
         first2->addReference(QQmlData::get(first1)->v8object);   // close the loop - circular ref across engines
-        // now we have to reparent and change ownership to JS.
+        // now we have to reparent and change ownership to JS, and remove property references.
         first1->setParent(0);
         second1->setParent(0);
         first2->setParent(0);
@@ -4858,6 +5163,10 @@ void tst_qqmlecmascript::handleReferenceManagement()
         QQmlEngine::setObjectOwnership(second1, QQmlEngine::JavaScriptOwnership);
         QQmlEngine::setObjectOwnership(first2, QQmlEngine::JavaScriptOwnership);
         QQmlEngine::setObjectOwnership(second2, QQmlEngine::JavaScriptOwnership);
+        object1->setProperty("first", QVariant::fromValue<QObject*>(0));
+        object1->setProperty("second", QVariant::fromValue<QObject*>(0));
+        object2->setProperty("first", QVariant::fromValue<QObject*>(0));
+        object2->setProperty("second", QVariant::fromValue<QObject*>(0));
         gc(engine);
         QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
         QCoreApplication::processEvents();
@@ -4926,6 +5235,57 @@ void tst_qqmlecmascript::handleReferenceManagement()
         QCoreApplication::processEvents();
         QCOMPARE(dtorCount, 6); // all objects should have been cleaned up prior to deleting hrmEngine1.
     }
+
+    {
+        // Dynamic variant property reference keeps target alive
+        QQmlEngine hrmEngine;
+        QQmlComponent component(&hrmEngine, testFileUrl("handleReferenceManagement.dynprop.qml"));
+        QObject *object = component.create();
+        QVERIFY(object != 0);
+        QMetaObject::invokeMethod(object, "createReference");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "ensureReference");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "removeReference");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "ensureDeletion");
+        QCOMPARE(object->property("success").toBool(), true);
+        delete object;
+    }
+
+    {
+        // Dynamic Item property reference keeps target alive
+        QQmlEngine hrmEngine;
+        QQmlComponent component(&hrmEngine, testFileUrl("handleReferenceManagement.dynprop.2.qml"));
+        QObject *object = component.create();
+        QVERIFY(object != 0);
+        QMetaObject::invokeMethod(object, "createReference");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "ensureReference");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "removeReference");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "ensureDeletion");
+        QCOMPARE(object->property("success").toBool(), true);
+        delete object;
+    }
+
+    {
+        // Item property reference to deleted item doesn't crash
+        QQmlEngine hrmEngine;
+        QQmlComponent component(&hrmEngine, testFileUrl("handleReferenceManagement.dynprop.3.qml"));
+        QObject *object = component.create();
+        QVERIFY(object != 0);
+        QMetaObject::invokeMethod(object, "createReference");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "ensureReference");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "manuallyDelete");
+        gc(engine);
+        QMetaObject::invokeMethod(object, "ensureDeleted");
+        QCOMPARE(object->property("success").toBool(), true);
+        delete object;
+    }
 }
 
 void tst_qqmlecmascript::stringArg()
@@ -5022,19 +5382,19 @@ void tst_qqmlecmascript::sequenceConversionRead()
         MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco");
         QVERIFY(seq != 0);
 
-        // we haven't registered QList<QPoint> as a sequence type.
-        QString warningOne = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'QList<QPoint>' for property 'MySequenceConversionObject::pointListProperty'");
+        // we haven't registered QList<NonRegisteredType> as a sequence type.
+        QString warningOne = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'QList<NonRegisteredType>' for property 'MySequenceConversionObject::typeListProperty'");
         QString warningTwo = qmlFile.toString() + QLatin1String(":18: TypeError: Cannot read property 'length' of undefined");
         QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData());
         QTest::ignoreMessage(QtWarningMsg, warningTwo.toLatin1().constData());
 
         QMetaObject::invokeMethod(object, "performTest");
 
-        // QList<QPoint> has not been registered as a sequence type.
+        // QList<NonRegisteredType> has not been registered as a sequence type.
         QCOMPARE(object->property("pointListLength").toInt(), 0);
         QVERIFY(!object->property("pointList").isValid());
-        QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::read: Unable to handle unregistered datatype 'QList<QPoint>' for property 'MySequenceConversionObject::pointListProperty'");
-        QQmlProperty seqProp(seq, "pointListProperty", &engine);
+        QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::read: Unable to handle unregistered datatype 'QList<NonRegisteredType>' for property 'MySequenceConversionObject::typeListProperty'");
+        QQmlProperty seqProp(seq, "typeListProperty", &engine);
         QVERIFY(!seqProp.read().isValid()); // not a valid/known sequence type
 
         delete object;
@@ -5203,6 +5563,10 @@ void tst_qqmlecmascript::sequenceConversionCopy()
     QCOMPARE(object->property("success").toBool(), true);
     QMetaObject::invokeMethod(object, "testEqualitySemantics");
     QCOMPARE(object->property("success").toBool(), true);
+    QMetaObject::invokeMethod(object, "testCopyParameters");
+    QCOMPARE(object->property("success").toBool(), true);
+    QMetaObject::invokeMethod(object, "testReferenceParameters");
+    QCOMPARE(object->property("success").toBool(), true);
     delete object;
 }
 
@@ -5493,9 +5857,11 @@ void tst_qqmlecmascript::functionAssignment_fromBinding()
     QString w1 = url + ":4:25: Unable to assign a function to a property of any type other than var.";
     QString w2 = url + ":5:25: Invalid use of Qt.binding() in a binding declaration.";
     QString w3 = url + ":6:21: Invalid use of Qt.binding() in a binding declaration.";
+    QString w4 = url + ":7:15: Invalid use of Qt.binding() in a binding declaration.";
     QTest::ignoreMessage(QtWarningMsg, w1.toLatin1().constData());
     QTest::ignoreMessage(QtWarningMsg, w2.toLatin1().constData());
     QTest::ignoreMessage(QtWarningMsg, w3.toLatin1().constData());
+    QTest::ignoreMessage(QtWarningMsg, w4.toLatin1().constData());
 
     MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
     QVERIFY(o != 0);
@@ -5568,15 +5934,13 @@ void tst_qqmlecmascript::functionAssignment_afterBinding()
     QQmlComponent component(&engine, testFileUrl("functionAssignment.3.qml"));
 
     QString url = component.url().toString();
-    //QString w1 = url + ":16: Error: Cannot assign JavaScript function to int"; // for now, function assignment = binding assignment
-    QString w1 = QLatin1String("WARNING: function assignment is DEPRECATED and will be removed!  Wrap RHS in Qt.binding(): ") + url + QLatin1String(":16");
+    QString w1 = url + ":16: Error: Cannot assign JavaScript function to int";
     QTest::ignoreMessage(QtWarningMsg, w1.toLatin1().constData());
 
     QObject *o = component.create();
     QVERIFY(o != 0);
     QCOMPARE(o->property("t1"), QVariant::fromValue<int>(4)); // should have bound
-    //QCOMPARE(o->property("t2"), QVariant::fromValue<int>(2)); // should not have changed
-    QCOMPARE(o->property("t2"), QVariant::fromValue<int>(4)); // for now, function assignment = binding assignment
+    QCOMPARE(o->property("t2"), QVariant::fromValue<int>(2)); // should not have changed
 
     delete o;
 }
@@ -6650,6 +7014,7 @@ void tst_qqmlecmascript::replaceBinding()
 
 void tst_qqmlecmascript::deleteRootObjectInCreation()
 {
+    {
     QQmlEngine engine;
     QQmlComponent c(&engine, testFileUrl("deleteRootObjectInCreation.qml"));
     QObject *obj = c.create();
@@ -6659,6 +7024,15 @@ void tst_qqmlecmascript::deleteRootObjectInCreation()
     QTest::qWait(1);
     QVERIFY(obj->property("childDestructible").toBool());
     delete obj;
+    }
+
+    {
+    QQmlComponent c(&engine, testFileUrl("deleteRootObjectInCreation.2.qml"));
+    QObject *object = c.create();
+    QVERIFY(object != 0);
+    QVERIFY(object->property("testConditionsMet").toBool());
+    delete object;
+    }
 }
 
 void tst_qqmlecmascript::onDestruction()
@@ -6717,16 +7091,6 @@ void tst_qqmlecmascript::bindingSuppression()
 void tst_qqmlecmascript::signalEmitted()
 {
     {
-        // calling destroy on the parent.
-        QQmlEngine engine;
-        QQmlComponent c(&engine, testFileUrl("signalEmitted.qml"));
-        QObject *obj = c.create();
-        QVERIFY(obj != 0);
-        QTRY_VERIFY(obj->property("success").toBool());
-        delete obj;
-    }
-
-    {
         // calling destroy on the sibling.
         QQmlEngine engine;
         QQmlComponent c(&engine, testFileUrl("signalEmitted.2.qml"));
@@ -6755,7 +7119,7 @@ void tst_qqmlecmascript::signalEmitted()
         QVERIFY(obj != 0);
         gc(engine); // should collect c1.
         QMetaObject::invokeMethod(obj, "destroyC2");
-        QTRY_VERIFY(obj->property("success").toBool());
+        QTRY_VERIFY(obj->property("success").toBool()); // handles events (incl. delete later).
         delete obj;
     }
 }
@@ -6763,11 +7127,171 @@ void tst_qqmlecmascript::signalEmitted()
 // QTBUG-25647
 void tst_qqmlecmascript::threadSignal()
 {
+    {
     QQmlComponent c(&engine, testFileUrl("threadSignal.qml"));
     QObject *object = c.create();
     QVERIFY(object != 0);
     QTRY_VERIFY(object->property("passed").toBool());
     delete object;
+    }
+    {
+    QQmlComponent c(&engine, testFileUrl("threadSignal.2.qml"));
+    QObject *object = c.create();
+    QVERIFY(object != 0);
+    QSignalSpy doneSpy(object, SIGNAL(done(const QString &)));
+    QMetaObject::invokeMethod(object, "doIt");
+    QTRY_VERIFY(object->property("passed").toBool());
+    QCOMPARE(doneSpy.count(), 1);
+    delete object;
+    }
+}
+
+// ensure that the qqmldata::destroyed() handler doesn't cause problems
+void tst_qqmlecmascript::qqmldataDestroyed()
+{
+    // gc cleans up a qobject, later the qqmldata destroyed handler will run.
+    {
+        QQmlComponent c(&engine, testFileUrl("qqmldataDestroyed.qml"));
+        QObject *object = c.create();
+        QVERIFY(object != 0);
+        // now gc causing the collection of the dynamically constructed object.
+        engine.collectGarbage();
+        engine.collectGarbage();
+        // now process events to allow deletion (calling qqmldata::destroyed())
+        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+        QCoreApplication::processEvents();
+        // shouldn't crash.
+        delete object;
+    }
+
+    // in this case, the object has CPP ownership, and the gc will
+    // be triggered during its beginCreate stage.
+    {
+        QQmlComponent c(&engine, testFileUrl("qqmldataDestroyed.2.qml"));
+        QObject *object = c.create();
+        QVERIFY(object != 0);
+        QVERIFY(object->property("testConditionsMet").toBool());
+        // the gc() within the handler will have triggered the weak
+        // qobject reference callback.  If that incorrectly disposes
+        // the handle, when the qqmldata::destroyed() handler is
+        // called due to object deletion we will see a crash.
+        delete object;
+        // shouldn't have crashed.
+    }
+}
+
+void tst_qqmlecmascript::secondAlias()
+{
+    QQmlComponent c(&engine, testFileUrl("secondAlias.qml"));
+    QObject *object = c.create();
+    QVERIFY(object != 0);
+    QCOMPARE(object->property("test").toInt(), 200);
+    delete object;
+}
+
+// An alias to a var property works
+void tst_qqmlecmascript::varAlias()
+{
+    QQmlComponent c(&engine, testFileUrl("varAlias.qml"));
+    QObject *object = c.create();
+    QVERIFY(object != 0);
+    QCOMPARE(object->property("test").toInt(), 192);
+    delete object;
+}
+
+// Used to trigger an assert in the lazy meta object creation stage
+void tst_qqmlecmascript::overrideDataAssert()
+{
+    QQmlComponent c(&engine, testFileUrl("overrideDataAssert.qml"));
+    QObject *object = c.create();
+    QVERIFY(object != 0);
+    object->metaObject();
+    delete object;
+}
+
+void tst_qqmlecmascript::fallbackBindings_data()
+{
+    QTest::addColumn<QString>("source");
+
+    QTest::newRow("Property without fallback") << "fallbackBindings.1.qml";
+    QTest::newRow("Property fallback") << "fallbackBindings.2.qml";
+    QTest::newRow("SingletonType without fallback") << "fallbackBindings.3.qml";
+    QTest::newRow("SingletonType fallback") << "fallbackBindings.4.qml";
+    QTest::newRow("Attached without fallback") << "fallbackBindings.5.qml";
+    QTest::newRow("Attached fallback") << "fallbackBindings.6.qml";
+    QTest::newRow("Subproperty without fallback") << "fallbackBindings.7.qml";
+    QTest::newRow("Subproperty fallback") << "fallbackBindings.8.qml";
+}
+
+void tst_qqmlecmascript::fallbackBindings()
+{
+    QFETCH(QString, source);
+
+    QQmlComponent component(&engine, testFileUrl(source));
+    QScopedPointer<QObject> object(component.create());
+    QVERIFY(object != 0);
+
+    QCOMPARE(object->property("success").toBool(), true);
+}
+
+void tst_qqmlecmascript::propertyOverride()
+{
+    QQmlComponent component(&engine, testFileUrl("propertyOverride.qml"));
+    QScopedPointer<QObject> object(component.create());
+    QVERIFY(object != 0);
+
+    QCOMPARE(object->property("success").toBool(), true);
+}
+
+void tst_qqmlecmascript::sequenceSort_data()
+{
+    QTest::addColumn<QString>("function");
+    QTest::addColumn<bool>("useComparer");
+
+    QTest::newRow("qtbug_25269") << "test_qtbug_25269" << false;
+
+    const char *types[] = { "alphabet", "numbers", "reals" };
+    const char *sort[] = { "insertionSort", "quickSort" };
+
+    for (size_t t=0 ; t < sizeof(types)/sizeof(types[0]) ; ++t) {
+        for (size_t s=0 ; s < sizeof(sort)/sizeof(sort[0]) ; ++s) {
+            for (int c=0 ; c < 2 ; ++c) {
+                QString testName = QLatin1String(types[t]) + QLatin1String("_") + QLatin1String(sort[s]);
+                QString fnName = QLatin1String("test_") + testName;
+                bool useComparer = c != 0;
+                testName += useComparer ? QLatin1String("[custom]") : QLatin1String("[default]");
+                QTest::newRow(testName.toAscii().constData()) << fnName << useComparer;
+            }
+        }
+    }
+}
+
+void tst_qqmlecmascript::sequenceSort()
+{
+    QFETCH(QString, function);
+    QFETCH(bool, useComparer);
+
+    QQmlComponent component(&engine, testFileUrl("sequenceSort.qml"));
+
+    QObject *object = component.create();
+    if (object == 0)
+        qDebug() << component.errorString();
+    QVERIFY(object != 0);
+
+    QVariant q;
+    QMetaObject::invokeMethod(object, function.toAscii().constData(), Q_RETURN_ARG(QVariant, q), Q_ARG(QVariant, useComparer));
+    QVERIFY(q.toBool() == true);
+
+    delete object;
+}
+
+void tst_qqmlecmascript::concatenatedStringPropertyAccess()
+{
+    QQmlComponent component(&engine, testFileUrl("concatenatedStringPropertyAccess.qml"));
+    QObject *object = component.create();
+    QVERIFY(object);
+    QVERIFY(object->property("success").toBool());
+    delete object;
 }
 
 QTEST_MAIN(tst_qqmlecmascript)