1 /**************************************************************************** |
1 /**************************************************************************** |
2 ** |
2 ** |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 ** All rights reserved. |
4 ** All rights reserved. |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 ** |
6 ** |
7 ** This file is part of the test suite of the Qt Toolkit. |
7 ** This file is part of the test suite of the Qt Toolkit. |
8 ** |
8 ** |
110 Q_PROPERTY(int writeOnlyProperty WRITE setWriteOnlyProperty) |
110 Q_PROPERTY(int writeOnlyProperty WRITE setWriteOnlyProperty) |
111 Q_PROPERTY(int readOnlyProperty READ readOnlyProperty) |
111 Q_PROPERTY(int readOnlyProperty READ readOnlyProperty) |
112 Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) |
112 Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) |
113 Q_PROPERTY(CustomType propWithCustomType READ propWithCustomType WRITE setPropWithCustomType) |
113 Q_PROPERTY(CustomType propWithCustomType READ propWithCustomType WRITE setPropWithCustomType) |
114 Q_PROPERTY(Policy enumProperty READ enumProperty WRITE setEnumProperty) |
114 Q_PROPERTY(Policy enumProperty READ enumProperty WRITE setEnumProperty) |
|
115 Q_PROPERTY(Ability flagsProperty READ flagsProperty WRITE setFlagsProperty) |
115 Q_ENUMS(Policy Strategy) |
116 Q_ENUMS(Policy Strategy) |
116 Q_FLAGS(Ability) |
117 Q_FLAGS(Ability) |
117 |
118 |
118 public: |
119 public: |
119 enum Policy { |
120 enum Policy { |
148 m_brushValue(QColor(10, 20, 30, 40)), |
149 m_brushValue(QColor(10, 20, 30, 40)), |
149 m_hiddenValue(456.0), |
150 m_hiddenValue(456.0), |
150 m_writeOnlyValue(789), |
151 m_writeOnlyValue(789), |
151 m_readOnlyValue(987), |
152 m_readOnlyValue(987), |
152 m_enumValue(BarPolicy), |
153 m_enumValue(BarPolicy), |
|
154 m_flagsValue(FooAbility), |
153 m_qtFunctionInvoked(-1) |
155 m_qtFunctionInvoked(-1) |
154 { } |
156 { } |
155 |
157 |
156 int intProperty() const |
158 int intProperty() const |
157 { return m_intValue; } |
159 { return m_intValue; } |
213 |
215 |
214 Policy enumProperty() const |
216 Policy enumProperty() const |
215 { return m_enumValue; } |
217 { return m_enumValue; } |
216 void setEnumProperty(Policy policy) |
218 void setEnumProperty(Policy policy) |
217 { m_enumValue = policy; } |
219 { m_enumValue = policy; } |
|
220 |
|
221 Ability flagsProperty() const |
|
222 { return m_flagsValue; } |
|
223 void setFlagsProperty(Ability ability) |
|
224 { m_flagsValue = ability; } |
218 |
225 |
219 int qtFunctionInvoked() const |
226 int qtFunctionInvoked() const |
220 { return m_qtFunctionInvoked; } |
227 { return m_qtFunctionInvoked; } |
221 |
228 |
222 QVariantList qtFunctionActuals() const |
229 QVariantList qtFunctionActuals() const |
314 { m_qtFunctionInvoked = 55; m_actuals << qVariantFromValue(arg); } |
321 { m_qtFunctionInvoked = 55; m_actuals << qVariantFromValue(arg); } |
315 Q_INVOKABLE QScriptValue myInvokableWithScriptValueArg(const QScriptValue &arg) |
322 Q_INVOKABLE QScriptValue myInvokableWithScriptValueArg(const QScriptValue &arg) |
316 { m_qtFunctionInvoked = 56; return arg; } |
323 { m_qtFunctionInvoked = 56; return arg; } |
317 Q_INVOKABLE QObject* myInvokableReturningMyQObjectAsQObject() |
324 Q_INVOKABLE QObject* myInvokableReturningMyQObjectAsQObject() |
318 { m_qtFunctionInvoked = 57; return this; } |
325 { m_qtFunctionInvoked = 57; return this; } |
|
326 Q_INVOKABLE Ability myInvokableWithFlagsArg(Ability arg) |
|
327 { m_qtFunctionInvoked = 58; m_actuals << int(arg); return arg; } |
|
328 Q_INVOKABLE MyQObject::Ability myInvokableWithQualifiedFlagsArg(MyQObject::Ability arg) |
|
329 { m_qtFunctionInvoked = 59; m_actuals << int(arg); return arg; } |
319 |
330 |
320 Q_INVOKABLE QObjectList findObjects() const |
331 Q_INVOKABLE QObjectList findObjects() const |
321 { return findChildren<QObject *>(); } |
332 { return findChildren<QObject *>(); } |
322 Q_INVOKABLE QList<int> myInvokableNumbers() const |
333 Q_INVOKABLE QList<int> myInvokableNumbers() const |
323 { return QList<int>() << 1 << 2 << 3; } |
334 { return QList<int>() << 1 << 2 << 3; } |
431 int m_writeOnlyValue; |
442 int m_writeOnlyValue; |
432 int m_readOnlyValue; |
443 int m_readOnlyValue; |
433 QKeySequence m_shortcut; |
444 QKeySequence m_shortcut; |
434 CustomType m_customType; |
445 CustomType m_customType; |
435 Policy m_enumValue; |
446 Policy m_enumValue; |
|
447 Ability m_flagsValue; |
436 int m_qtFunctionInvoked; |
448 int m_qtFunctionInvoked; |
437 QVariantList m_actuals; |
449 QVariantList m_actuals; |
438 QByteArray m_connectedSignal; |
450 QByteArray m_connectedSignal; |
439 QByteArray m_disconnectedSignal; |
451 QByteArray m_disconnectedSignal; |
440 }; |
452 }; |
518 void enumerateSpecial(); |
530 void enumerateSpecial(); |
519 void wrapOptions(); |
531 void wrapOptions(); |
520 void prototypes(); |
532 void prototypes(); |
521 void objectDeleted(); |
533 void objectDeleted(); |
522 void connectToDestroyedSignal(); |
534 void connectToDestroyedSignal(); |
|
535 void emitAfterReceiverDeleted(); |
523 |
536 |
524 private: |
537 private: |
525 QScriptEngine *m_engine; |
538 QScriptEngine *m_engine; |
526 MyQObject *m_myObject; |
539 MyQObject *m_myObject; |
527 QScriptValue m_signalHandlerException; |
540 QScriptValue m_signalHandlerException; |
824 // enum property |
837 // enum property |
825 QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy); |
838 QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy); |
826 { |
839 { |
827 QScriptValue val = m_engine->evaluate("myObject.enumProperty"); |
840 QScriptValue val = m_engine->evaluate("myObject.enumProperty"); |
828 QVERIFY(val.isNumber()); |
841 QVERIFY(val.isNumber()); |
829 QCOMPARE(val.toInt32(), (int)MyQObject::BarPolicy); |
842 QCOMPARE(val.toInt32(), int(MyQObject::BarPolicy)); |
830 } |
843 } |
831 m_engine->evaluate("myObject.enumProperty = 2"); |
844 m_engine->evaluate("myObject.enumProperty = 2"); |
832 QCOMPARE(m_myObject->enumProperty(), MyQObject::BazPolicy); |
845 QCOMPARE(m_myObject->enumProperty(), MyQObject::BazPolicy); |
833 m_engine->evaluate("myObject.enumProperty = 'BarPolicy'"); |
846 m_engine->evaluate("myObject.enumProperty = 'BarPolicy'"); |
834 QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy); |
847 QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy); |
843 QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy); |
856 QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy); |
844 m_engine->evaluate("myObject.enumProperty = 'blue'"); |
857 m_engine->evaluate("myObject.enumProperty = 'blue'"); |
845 QCOMPARE(m_myObject->enumProperty(), MyQObject::BazPolicy); |
858 QCOMPARE(m_myObject->enumProperty(), MyQObject::BazPolicy); |
846 m_engine->evaluate("myObject.enumProperty = 'nada'"); |
859 m_engine->evaluate("myObject.enumProperty = 'nada'"); |
847 QCOMPARE(m_myObject->enumProperty(), (MyQObject::Policy)-1); |
860 QCOMPARE(m_myObject->enumProperty(), (MyQObject::Policy)-1); |
|
861 |
|
862 // flags property |
|
863 QCOMPARE(m_myObject->flagsProperty(), MyQObject::FooAbility); |
|
864 { |
|
865 QScriptValue val = m_engine->evaluate("myObject.flagsProperty"); |
|
866 QVERIFY(val.isNumber()); |
|
867 QCOMPARE(val.toInt32(), int(MyQObject::FooAbility)); |
|
868 } |
|
869 m_engine->evaluate("myObject.flagsProperty = 0x80"); |
|
870 QCOMPARE(m_myObject->flagsProperty(), MyQObject::BarAbility); |
|
871 m_engine->evaluate("myObject.flagsProperty = 0x81"); |
|
872 QCOMPARE(m_myObject->flagsProperty(), MyQObject::Ability(MyQObject::FooAbility | MyQObject::BarAbility)); |
|
873 m_engine->evaluate("myObject.flagsProperty = 123"); // bogus values are accepted |
|
874 QCOMPARE(int(m_myObject->flagsProperty()), 123); |
|
875 m_engine->evaluate("myObject.flagsProperty = 'BazAbility'"); |
|
876 QCOMPARE(m_myObject->flagsProperty(), MyQObject::BazAbility); |
|
877 m_engine->evaluate("myObject.flagsProperty = 'ScoobyDoo'"); |
|
878 // ### ouch! Shouldn't QMetaProperty::write() rather not change the value...? |
|
879 QCOMPARE(m_myObject->flagsProperty(), (MyQObject::Ability)-1); |
848 |
880 |
849 // auto-dereferencing of pointers |
881 // auto-dereferencing of pointers |
850 { |
882 { |
851 QBrush b = QColor(0xCA, 0xFE, 0xBA, 0xBE); |
883 QBrush b = QColor(0xCA, 0xFE, 0xBA, 0xBE); |
852 QBrush *bp = &b; |
884 QBrush *bp = &b; |
2015 void tst_QScriptExtQObject::classEnums() |
2047 void tst_QScriptExtQObject::classEnums() |
2016 { |
2048 { |
2017 QScriptValue myClass = m_engine->newQMetaObject(m_myObject->metaObject(), m_engine->undefinedValue()); |
2049 QScriptValue myClass = m_engine->newQMetaObject(m_myObject->metaObject(), m_engine->undefinedValue()); |
2018 m_engine->globalObject().setProperty("MyQObject", myClass); |
2050 m_engine->globalObject().setProperty("MyQObject", myClass); |
2019 |
2051 |
|
2052 QVERIFY(m_engine->evaluate("MyQObject.FooPolicy").isNumber()); // no strong typing |
2020 QCOMPARE(static_cast<MyQObject::Policy>(m_engine->evaluate("MyQObject.FooPolicy").toInt32()), |
2053 QCOMPARE(static_cast<MyQObject::Policy>(m_engine->evaluate("MyQObject.FooPolicy").toInt32()), |
2021 MyQObject::FooPolicy); |
2054 MyQObject::FooPolicy); |
2022 QCOMPARE(static_cast<MyQObject::Policy>(m_engine->evaluate("MyQObject.BarPolicy").toInt32()), |
2055 QCOMPARE(static_cast<MyQObject::Policy>(m_engine->evaluate("MyQObject.BarPolicy").toInt32()), |
2023 MyQObject::BarPolicy); |
2056 MyQObject::BarPolicy); |
2024 QCOMPARE(static_cast<MyQObject::Policy>(m_engine->evaluate("MyQObject.BazPolicy").toInt32()), |
2057 QCOMPARE(static_cast<MyQObject::Policy>(m_engine->evaluate("MyQObject.BazPolicy").toInt32()), |
2029 QCOMPARE(static_cast<MyQObject::Strategy>(m_engine->evaluate("MyQObject.BarStrategy").toInt32()), |
2062 QCOMPARE(static_cast<MyQObject::Strategy>(m_engine->evaluate("MyQObject.BarStrategy").toInt32()), |
2030 MyQObject::BarStrategy); |
2063 MyQObject::BarStrategy); |
2031 QCOMPARE(static_cast<MyQObject::Strategy>(m_engine->evaluate("MyQObject.BazStrategy").toInt32()), |
2064 QCOMPARE(static_cast<MyQObject::Strategy>(m_engine->evaluate("MyQObject.BazStrategy").toInt32()), |
2032 MyQObject::BazStrategy); |
2065 MyQObject::BazStrategy); |
2033 |
2066 |
|
2067 QVERIFY(m_engine->evaluate("MyQObject.NoAbility").isNumber()); // no strong typing |
2034 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.NoAbility").toInt32()), |
2068 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.NoAbility").toInt32()), |
2035 MyQObject::NoAbility); |
2069 MyQObject::NoAbility); |
2036 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.FooAbility").toInt32()), |
2070 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.FooAbility").toInt32()), |
2037 MyQObject::FooAbility); |
2071 MyQObject::FooAbility); |
2038 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.BarAbility").toInt32()), |
2072 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.BarAbility").toInt32()), |
2040 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.BazAbility").toInt32()), |
2074 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.BazAbility").toInt32()), |
2041 MyQObject::BazAbility); |
2075 MyQObject::BazAbility); |
2042 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.AllAbility").toInt32()), |
2076 QCOMPARE(MyQObject::Ability(m_engine->evaluate("MyQObject.AllAbility").toInt32()), |
2043 MyQObject::AllAbility); |
2077 MyQObject::AllAbility); |
2044 |
2078 |
|
2079 // Constructors for flags are not provided |
|
2080 QVERIFY(m_engine->evaluate("MyQObject.Ability").isUndefined()); |
|
2081 |
2045 QScriptValue::PropertyFlags expectedEnumFlags = QScriptValue::ReadOnly | QScriptValue::Undeletable; |
2082 QScriptValue::PropertyFlags expectedEnumFlags = QScriptValue::ReadOnly | QScriptValue::Undeletable; |
2046 QCOMPARE(myClass.propertyFlags("FooPolicy"), expectedEnumFlags); |
2083 QCOMPARE(myClass.propertyFlags("FooPolicy"), expectedEnumFlags); |
2047 QCOMPARE(myClass.propertyFlags("BarPolicy"), expectedEnumFlags); |
2084 QCOMPARE(myClass.propertyFlags("BarPolicy"), expectedEnumFlags); |
2048 QCOMPARE(myClass.propertyFlags("BazPolicy"), expectedEnumFlags); |
2085 QCOMPARE(myClass.propertyFlags("BazPolicy"), expectedEnumFlags); |
2049 |
2086 |
2090 { |
2127 { |
2091 QScriptValue ret = m_engine->evaluate("myObject.myInvokableReturningQualifiedEnum()"); |
2128 QScriptValue ret = m_engine->evaluate("myObject.myInvokableReturningQualifiedEnum()"); |
2092 QCOMPARE(m_myObject->qtFunctionInvoked(), 38); |
2129 QCOMPARE(m_myObject->qtFunctionInvoked(), 38); |
2093 QCOMPARE(m_myObject->qtFunctionActuals().size(), 0); |
2130 QCOMPARE(m_myObject->qtFunctionActuals().size(), 0); |
2094 QCOMPARE(ret.isNumber(), true); |
2131 QCOMPARE(ret.isNumber(), true); |
|
2132 } |
|
2133 |
|
2134 m_myObject->resetQtFunctionInvoked(); |
|
2135 { |
|
2136 QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithFlagsArg(MyQObject.FooAbility)"); |
|
2137 QCOMPARE(m_myObject->qtFunctionInvoked(), 58); |
|
2138 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
2139 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), int(MyQObject::FooAbility)); |
|
2140 QCOMPARE(ret.isNumber(), true); |
|
2141 QCOMPARE(ret.toInt32(), int(MyQObject::FooAbility)); |
|
2142 } |
|
2143 m_myObject->resetQtFunctionInvoked(); |
|
2144 { |
|
2145 QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithQualifiedFlagsArg(MyQObject.BarAbility)"); |
|
2146 QCOMPARE(m_myObject->qtFunctionInvoked(), 59); |
|
2147 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
2148 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), int(MyQObject::BarAbility)); |
|
2149 QCOMPARE(ret.isNumber(), true); |
|
2150 QCOMPARE(ret.toInt32(), int(MyQObject::BarAbility)); |
2095 } |
2151 } |
2096 |
2152 |
2097 // enum properties are not deletable or writable |
2153 // enum properties are not deletable or writable |
2098 QVERIFY(!m_engine->evaluate("delete MyQObject.BazPolicy").toBool()); |
2154 QVERIFY(!m_engine->evaluate("delete MyQObject.BazPolicy").toBool()); |
2099 myClass.setProperty("BazPolicy", QScriptValue()); |
2155 myClass.setProperty("BazPolicy", QScriptValue()); |
2856 v.setProperty("objectName", QScriptValue(&eng, "foo")); |
2912 v.setProperty("objectName", QScriptValue(&eng, "foo")); |
2857 QCOMPARE(qobj->objectName(), QLatin1String("foo")); |
2913 QCOMPARE(qobj->objectName(), QLatin1String("foo")); |
2858 v.setProperty("intProperty", QScriptValue(&eng, 123)); |
2914 v.setProperty("intProperty", QScriptValue(&eng, 123)); |
2859 QCOMPARE(qobj->intProperty(), 123); |
2915 QCOMPARE(qobj->intProperty(), 123); |
2860 qobj->resetQtFunctionInvoked(); |
2916 qobj->resetQtFunctionInvoked(); |
2861 v.property("myInvokable").call(v); |
2917 QScriptValue invokable = v.property("myInvokable"); |
|
2918 invokable.call(v); |
2862 QCOMPARE(qobj->qtFunctionInvoked(), 0); |
2919 QCOMPARE(qobj->qtFunctionInvoked(), 0); |
2863 |
2920 |
2864 // now delete the object |
2921 // now delete the object |
2865 delete qobj; |
2922 delete qobj; |
2866 |
2923 |
2892 // myInvokableWithIntArg is not stored in member table (since we've not accessed it) |
2949 // myInvokableWithIntArg is not stored in member table (since we've not accessed it) |
2893 { |
2950 { |
2894 QScriptValue ret = v.property("myInvokableWithIntArg"); |
2951 QScriptValue ret = v.property("myInvokableWithIntArg"); |
2895 QVERIFY(ret.isError()); |
2952 QVERIFY(ret.isError()); |
2896 QCOMPARE(ret.toString(), QLatin1String("Error: cannot access member `myInvokableWithIntArg' of deleted QObject")); |
2953 QCOMPARE(ret.toString(), QLatin1String("Error: cannot access member `myInvokableWithIntArg' of deleted QObject")); |
|
2954 } |
|
2955 |
|
2956 // Meta-method wrappers are still valid, but throw error when called |
|
2957 QVERIFY(invokable.isFunction()); |
|
2958 { |
|
2959 QScriptValue ret = invokable.call(v); |
|
2960 QVERIFY(ret.isError()); |
|
2961 QCOMPARE(ret.toString(), QString::fromLatin1("Error: cannot call function of deleted QObject")); |
2897 } |
2962 } |
2898 |
2963 |
2899 // access from script |
2964 // access from script |
2900 eng.globalObject().setProperty("o", v); |
2965 eng.globalObject().setProperty("o", v); |
2901 { |
2966 { |
2954 // the signal handler won't get called -- we don't want to crash |
3019 // the signal handler won't get called -- we don't want to crash |
2955 } |
3020 } |
2956 #endif |
3021 #endif |
2957 } |
3022 } |
2958 |
3023 |
|
3024 void tst_QScriptExtQObject::emitAfterReceiverDeleted() |
|
3025 { |
|
3026 for (int x = 0; x < 2; ++x) { |
|
3027 MyQObject *obj = new MyQObject; |
|
3028 QScriptValue scriptObj = m_engine->newQObject(obj); |
|
3029 if (x == 0) { |
|
3030 // Connecting from JS |
|
3031 m_engine->globalObject().setProperty("obj", scriptObj); |
|
3032 QVERIFY(m_engine->evaluate("myObject.mySignal.connect(obj, 'mySlot()')").isUndefined()); |
|
3033 } else { |
|
3034 // Connecting from C++ |
|
3035 qScriptConnect(m_myObject, SIGNAL(mySignal()), scriptObj, scriptObj.property("mySlot")); |
|
3036 } |
|
3037 delete obj; |
|
3038 QSignalSpy signalHandlerExceptionSpy(m_engine, SIGNAL(signalHandlerException(QScriptValue))); |
|
3039 QVERIFY(!m_engine->hasUncaughtException()); |
|
3040 m_myObject->emitMySignal(); |
|
3041 QCOMPARE(signalHandlerExceptionSpy.count(), 0); |
|
3042 QVERIFY(!m_engine->hasUncaughtException()); |
|
3043 } |
|
3044 } |
|
3045 |
2959 QTEST_MAIN(tst_QScriptExtQObject) |
3046 QTEST_MAIN(tst_QScriptExtQObject) |
2960 #include "tst_qscriptextqobject.moc" |
3047 #include "tst_qscriptextqobject.moc" |