diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-11-09 21:46:53 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-11-09 21:46:53 (GMT) |
commit | d9daad0ec3e3220c778177bb17d67158bde9c5aa (patch) | |
tree | d466de2143d81f0a20c3203193a7f2371c1ef48e | |
parent | 5b03f39a9dceac181abe304eb9be7647f6f166fb (diff) | |
parent | e1bcbc5bcf3d6015cacc717c31f96d2230890e88 (diff) | |
download | Qt-d9daad0ec3e3220c778177bb17d67158bde9c5aa.zip Qt-d9daad0ec3e3220c778177bb17d67158bde9c5aa.tar.gz Qt-d9daad0ec3e3220c778177bb17d67158bde9c5aa.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1:
Add autotests for setting non-Object as prototype value
Revert new flaky test
compile fix for namespaced Qt
Ensured that the document nodes are sorted in the generated index.
Make qsTr() work with Unicode (non-Latin-1) strings
Add autotest that checks return value of QScriptContext::throwXXX()
Improve autotest coverage of QScriptEngineDebugger
Add benchmark for emitting signals from QtScript
Split monolithic QtScript autotest into smaller tests
18 files changed, 517 insertions, 26 deletions
diff --git a/examples/webkit/imageanalyzer/imageanalyzer.h b/examples/webkit/imageanalyzer/imageanalyzer.h index 1bb25dc..5a96909 100644 --- a/examples/webkit/imageanalyzer/imageanalyzer.h +++ b/examples/webkit/imageanalyzer/imageanalyzer.h @@ -38,15 +38,17 @@ ** ****************************************************************************/ - #ifndef IMAGEANALYZER_H #define IMAGEANALYZER_H + #include <QFutureWatcher> #include <QtGui> +QT_BEGIN_NAMESPACE class QNetworkAccessManager; class QNetworkReply; class QNetworkDiskCache; +QT_END_NAMESPACE //! [ ImageAnalyzer - public interface ] class ImageAnalyzer : public QObject diff --git a/examples/webkit/imageanalyzer/mainwindow.h b/examples/webkit/imageanalyzer/mainwindow.h index 076e586..3c943dc 100644 --- a/examples/webkit/imageanalyzer/mainwindow.h +++ b/examples/webkit/imageanalyzer/mainwindow.h @@ -45,7 +45,9 @@ #include <QWebView> class ImageAnalyzer; +QT_BEGIN_NAMESPACE class QNetworkDiskCache; +QT_END_NAMESPACE class MainWin : public QWebView { diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 2d5e5f4..69abcad 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -808,7 +808,7 @@ JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObje JSC::UString comment; if (args.size() > 2) comment = args.at(2).toString(exec); - QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr; + QCoreApplication::Encoding encoding = QCoreApplication::UnicodeUTF8; if (args.size() > 3) { JSC::UString encStr = args.at(3).toString(exec); if (encStr == "CodecForTr") @@ -824,9 +824,9 @@ JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObje #endif JSC::UString result; #ifndef QT_NO_QOBJECT - result = QCoreApplication::translate(QScript::convertToLatin1(context).constData(), - QScript::convertToLatin1(text).constData(), - QScript::convertToLatin1(comment).constData(), + result = QCoreApplication::translate(context.UTF8String().c_str(), + text.UTF8String().c_str(), + comment.UTF8String().c_str(), encoding, n); #else result = text; @@ -878,10 +878,10 @@ JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JS #endif JSC::UString result; #ifndef QT_NO_QOBJECT - result = QCoreApplication::translate(QScript::convertToLatin1(context).constData(), - QScript::convertToLatin1(text).constData(), - QScript::convertToLatin1(comment).constData(), - QCoreApplication::CodecForTr, n); + result = QCoreApplication::translate(context.UTF8String().c_str(), + text.UTF8String().c_str(), + comment.UTF8String().c_str(), + QCoreApplication::UnicodeUTF8, n); #else result = text; #endif @@ -907,7 +907,7 @@ JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState *exec, JSC::JSObject*, int n = -1; if (args.size() > 1) n = args.at(1).toInt32(exec); - return JSC::jsString(exec, qtTrId(QScript::convertToLatin1(id).constData(), n)); + return JSC::jsString(exec, qtTrId(id.UTF8String().c_str(), n)); } JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index cbcd16a..5e7ede8 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -50,6 +50,7 @@ //TESTED_FILES= Q_DECLARE_METATYPE(QScriptValueList) +Q_DECLARE_METATYPE(QScriptContext::Error) QT_BEGIN_NAMESPACE extern bool qt_script_isJITEnabled(); @@ -91,6 +92,10 @@ private slots: void qobjectAsActivationObject(); void parentContextCallee_QT2270(); void popNativeContextScope(); + void throwErrorInGlobalContext(); + void throwErrorWithTypeInGlobalContext_data(); + void throwErrorWithTypeInGlobalContext(); + void throwValueInGlobalContext(); }; tst_QScriptContext::tst_QScriptContext() @@ -1323,5 +1328,49 @@ void tst_QScriptContext::parentContextCallee_QT2270() QVERIFY(callee.equals(fun)); } +void tst_QScriptContext::throwErrorInGlobalContext() +{ + QScriptEngine eng; + QScriptValue ret = eng.currentContext()->throwError("foo"); + QVERIFY(ret.isError()); + QVERIFY(eng.hasUncaughtException()); + QVERIFY(eng.uncaughtException().strictlyEquals(ret)); + QCOMPARE(ret.toString(), QString::fromLatin1("Error: foo")); +} + +void tst_QScriptContext::throwErrorWithTypeInGlobalContext_data() +{ + QTest::addColumn<QScriptContext::Error>("error"); + QTest::addColumn<QString>("stringRepresentation"); + QTest::newRow("ReferenceError") << QScriptContext::ReferenceError << QString::fromLatin1("ReferenceError: foo"); + QTest::newRow("SyntaxError") << QScriptContext::SyntaxError << QString::fromLatin1("SyntaxError: foo"); + QTest::newRow("TypeError") << QScriptContext::TypeError << QString::fromLatin1("TypeError: foo"); + QTest::newRow("RangeError") << QScriptContext::RangeError << QString::fromLatin1("RangeError: foo"); + QTest::newRow("URIError") << QScriptContext::URIError << QString::fromLatin1("URIError: foo"); + QTest::newRow("UnknownError") << QScriptContext::UnknownError << QString::fromLatin1("Error: foo"); +} + +void tst_QScriptContext::throwErrorWithTypeInGlobalContext() +{ + QFETCH(QScriptContext::Error, error); + QFETCH(QString, stringRepresentation); + QScriptEngine eng; + QScriptValue ret = eng.currentContext()->throwError(error, "foo"); + QVERIFY(ret.isError()); + QVERIFY(eng.hasUncaughtException()); + QVERIFY(eng.uncaughtException().strictlyEquals(ret)); + QCOMPARE(ret.toString(), stringRepresentation); +} + +void tst_QScriptContext::throwValueInGlobalContext() +{ + QScriptEngine eng; + QScriptValue val(&eng, 123); + QScriptValue ret = eng.currentContext()->throwValue(val); + QVERIFY(ret.strictlyEquals(val)); + QVERIFY(eng.hasUncaughtException()); + QVERIFY(eng.uncaughtException().strictlyEquals(val)); +} + QTEST_MAIN(tst_QScriptContext) #include "tst_qscriptcontext.moc" diff --git a/tests/auto/qscriptengine/idtranslatable-unicode.js b/tests/auto/qscriptengine/idtranslatable-unicode.js new file mode 100644 index 0000000..e17d617 --- /dev/null +++ b/tests/auto/qscriptengine/idtranslatable-unicode.js @@ -0,0 +1,5 @@ +qsTrId('\u01F8\u01D2\u0199\u01D0\u01E1'); + +QT_TRID_NOOP("\u0191\u01CE\u0211\u0229\u019C\u018E\u019A\u01D0"); + +qsTrId("\u0181\u01A1\u0213\u018F\u018C", 10); diff --git a/tests/auto/qscriptengine/qscriptengine.qrc b/tests/auto/qscriptengine/qscriptengine.qrc index fa55a5b..d05d115 100644 --- a/tests/auto/qscriptengine/qscriptengine.qrc +++ b/tests/auto/qscriptengine/qscriptengine.qrc @@ -2,5 +2,7 @@ <qresource> <file>translations/translatable_la.qm</file> <file>translations/idtranslatable_la.qm</file> + <file>translations/translatable-unicode.qm</file> + <file>translations/idtranslatable-unicode.qm</file> </qresource> </RCC> diff --git a/tests/auto/qscriptengine/translatable-unicode.js b/tests/auto/qscriptengine/translatable-unicode.js new file mode 100644 index 0000000..afe2aff --- /dev/null +++ b/tests/auto/qscriptengine/translatable-unicode.js @@ -0,0 +1,9 @@ +qsTr("H\u2082O"); +qsTranslate("\u010C\u0101\u011F\u0115", "CO\u2082"); + +var unicode_strings = [ + QT_TR_NOOP("\u0391\u0392\u0393"), + QT_TRANSLATE_NOOP("\u010C\u0101\u011F\u0115", "\u0414\u0415\u0416") +]; + +qsTr("H\u2082O", "not the same H\u2082O"); diff --git a/tests/auto/qscriptengine/translations/idtranslatable-unicode.qm b/tests/auto/qscriptengine/translations/idtranslatable-unicode.qm Binary files differnew file mode 100644 index 0000000..8c5fb91 --- /dev/null +++ b/tests/auto/qscriptengine/translations/idtranslatable-unicode.qm diff --git a/tests/auto/qscriptengine/translations/idtranslatable-unicode.ts b/tests/auto/qscriptengine/translations/idtranslatable-unicode.ts new file mode 100644 index 0000000..74ebf43 --- /dev/null +++ b/tests/auto/qscriptengine/translations/idtranslatable-unicode.ts @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.0" language="nb_NO"> +<defaultcodec>UTF-8</defaultcodec> +<context> + <name></name> + <message id="Ǹǒƙǐǡ"> + <location filename="idtranslatable-unicode.js" line="1"/> + <source></source> + <translation>Ƨưƈȼȝȿș</translation> + </message> + <message id="ƑǎȑȩƜƎƚǐ"> + <location filename="idtranslatable-unicode.js" line="3"/> + <source></source> + <translation>Ǡȡȋȅȕ</translation> + </message> + <message id="ƁơȓƏƌ" numerus="yes"> + <location filename="idtranslatable-unicode.js" line="5"/> + <source></source> + <translation> + <numerusform>Ƒưǹ</numerusform> + <numerusform>%n ƒơǒ(ș)</numerusform> + </translation> + </message> +</context> +</TS> diff --git a/tests/auto/qscriptengine/translations/translatable-unicode.qm b/tests/auto/qscriptengine/translations/translatable-unicode.qm Binary files differnew file mode 100644 index 0000000..aa75ce6 --- /dev/null +++ b/tests/auto/qscriptengine/translations/translatable-unicode.qm diff --git a/tests/auto/qscriptengine/translations/translatable-unicode.ts b/tests/auto/qscriptengine/translations/translatable-unicode.ts new file mode 100644 index 0000000..1b8b4d2 --- /dev/null +++ b/tests/auto/qscriptengine/translations/translatable-unicode.ts @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.0"> +<defaultcodec>UTF-8</defaultcodec> +<context> + <name>translatable-unicode</name> + <message> + <location filename="translatable-unicode.js" line="1"/> + <source>H₂O</source> + <translation>ͻͼͽ</translation> + </message> + <message> + <location filename="translatable-unicode.js" line="5"/> + <source>ΑΒΓ</source> + <translation>ӜҴѼ</translation> + </message> + <message> + <location filename="translatable-unicode.js" line="9"/> + <source>H₂O</source> + <comment>not the same H₂O</comment> + <translation>ԶՊՒ</translation> + </message> +</context> +<context> + <name>Čāğĕ</name> + <message> + <location filename="translatable-unicode.js" line="2"/> + <source>CO₂</source> + <translation>בךע</translation> + </message> + <message> + <location filename="translatable-unicode.js" line="6"/> + <source>ДЕЖ</source> + <translation>خسس</translation> + </message> +</context> +</TS> diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 5f38c22..d529b8b 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -186,6 +186,10 @@ private slots: void translationContext_data(); void translationContext(); void translateScriptIdBased(); + void translateScriptUnicode_data(); + void translateScriptUnicode(); + void translateScriptUnicodeIdBased_data(); + void translateScriptUnicodeIdBased(); void functionScopes(); void nativeFunctionScopes(); void evaluateProgram(); @@ -4950,6 +4954,93 @@ void tst_QScriptEngine::translateScriptIdBased() QString::fromLatin1("qtn_foo_bar")); // Doesn't have plural } +// How to add a new test row: +// - Find a nice list of Unicode characters to choose from +// - Write source string/context/comment in .js using Unicode escape sequences (\uABCD) +// - Update corresponding .ts file (e.g. lupdate foo.js -ts foo.ts -codecfortr UTF-8) +// - Enter translation in Linguist +// - Update corresponding .qm file (e.g. lrelease foo.ts) +// - Evaluate script that performs translation; make sure the correct result is returned +// (e.g. by setting the resulting string as the text of a QLabel and visually verifying +// that it looks the same as what you entered in Linguist :-) ) +// - Generate the expectedTranslation column data using toUtf8().toHex() +void tst_QScriptEngine::translateScriptUnicode_data() +{ + QTest::addColumn<QString>("expression"); + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QString>("expectedTranslation"); + + QString fileName = QString::fromLatin1("translatable-unicode.js"); + QTest::newRow("qsTr('H\\u2082O')@translatable-unicode.js") + << QString::fromLatin1("qsTr('H\\u2082O')") << fileName << QString::fromUtf8("\xcd\xbb\xcd\xbc\xcd\xbd"); + QTest::newRow("qsTranslate('\\u010C\\u0101\\u011F\\u0115', 'CO\\u2082')@translatable-unicode.js") + << QString::fromLatin1("qsTranslate('\\u010C\\u0101\\u011F\\u0115', 'CO\\u2082')") << fileName << QString::fromUtf8("\xd7\x91\xd7\x9a\xd7\xa2"); + QTest::newRow("qsTr('\\u0391\\u0392\\u0393')@translatable-unicode.js") + << QString::fromLatin1("qsTr('\\u0391\\u0392\\u0393')") << fileName << QString::fromUtf8("\xd3\x9c\xd2\xb4\xd1\xbc"); + QTest::newRow("qsTranslate('\\u010C\\u0101\\u011F\\u0115', '\\u0414\\u0415\\u0416')@translatable-unicode.js") + << QString::fromLatin1("qsTranslate('\\u010C\\u0101\\u011F\\u0115', '\\u0414\\u0415\\u0416')") << fileName << QString::fromUtf8("\xd8\xae\xd8\xb3\xd8\xb3"); + QTest::newRow("qsTr('H\\u2082O', 'not the same H\\u2082O')@translatable-unicode.js") + << QString::fromLatin1("qsTr('H\\u2082O', 'not the same H\\u2082O')") << fileName << QString::fromUtf8("\xd4\xb6\xd5\x8a\xd5\x92"); + QTest::newRow("qsTr('H\\u2082O')") + << QString::fromLatin1("qsTr('H\\u2082O')") << QString() << QString::fromUtf8("\x48\xe2\x82\x82\x4f"); + QTest::newRow("qsTranslate('\\u010C\\u0101\\u011F\\u0115', 'CO\\u2082')") + << QString::fromLatin1("qsTranslate('\\u010C\\u0101\\u011F\\u0115', 'CO\\u2082')") << QString() << QString::fromUtf8("\xd7\x91\xd7\x9a\xd7\xa2"); +} + +void tst_QScriptEngine::translateScriptUnicode() +{ + QFETCH(QString, expression); + QFETCH(QString, fileName); + QFETCH(QString, expectedTranslation); + + QScriptEngine engine; + + QTranslator translator; + QVERIFY(translator.load(":/translations/translatable-unicode")); + QCoreApplication::instance()->installTranslator(&translator); + engine.installTranslatorFunctions(); + + QCOMPARE(engine.evaluate(expression, fileName).toString(), expectedTranslation); + QVERIFY(!engine.hasUncaughtException()); + + QCoreApplication::instance()->removeTranslator(&translator); +} + +void tst_QScriptEngine::translateScriptUnicodeIdBased_data() +{ + QTest::addColumn<QString>("expression"); + QTest::addColumn<QString>("expectedTranslation"); + + QTest::newRow("qsTrId('\\u01F8\\u01D2\\u0199\\u01D0\\u01E1'')") + << QString::fromLatin1("qsTrId('\\u01F8\\u01D2\\u0199\\u01D0\\u01E1')") << QString::fromUtf8("\xc6\xa7\xc6\xb0\xc6\x88\xc8\xbc\xc8\x9d\xc8\xbf\xc8\x99"); + QTest::newRow("qsTrId('\\u0191\\u01CE\\u0211\\u0229\\u019C\\u018E\\u019A\\u01D0')") + << QString::fromLatin1("qsTrId('\\u0191\\u01CE\\u0211\\u0229\\u019C\\u018E\\u019A\\u01D0')") << QString::fromUtf8("\xc7\xa0\xc8\xa1\xc8\x8b\xc8\x85\xc8\x95"); + QTest::newRow("qsTrId('\\u0181\\u01A1\\u0213\\u018F\\u018C', 10)") + << QString::fromLatin1("qsTrId('\\u0181\\u01A1\\u0213\\u018F\\u018C', 10)") << QString::fromUtf8("\x31\x30\x20\xc6\x92\xc6\xa1\xc7\x92\x28\xc8\x99\x29"); + QTest::newRow("qsTrId('\\u0181\\u01A1\\u0213\\u018F\\u018C')") + << QString::fromLatin1("qsTrId('\\u0181\\u01A1\\u0213\\u018F\\u018C')") << QString::fromUtf8("\xc6\x91\xc6\xb0\xc7\xb9"); + QTest::newRow("qsTrId('\\u01CD\\u0180\\u01A8\\u0190\\u019E\\u01AB')") + << QString::fromLatin1("qsTrId('\\u01CD\\u0180\\u01A8\\u0190\\u019E\\u01AB')") << QString::fromUtf8("\xc7\x8d\xc6\x80\xc6\xa8\xc6\x90\xc6\x9e\xc6\xab"); +} + +void tst_QScriptEngine::translateScriptUnicodeIdBased() +{ + QFETCH(QString, expression); + QFETCH(QString, expectedTranslation); + + QScriptEngine engine; + + QTranslator translator; + QVERIFY(translator.load(":/translations/idtranslatable-unicode")); + QCoreApplication::instance()->installTranslator(&translator); + engine.installTranslatorFunctions(); + + QCOMPARE(engine.evaluate(expression).toString(), expectedTranslation); + QVERIFY(!engine.hasUncaughtException()); + + QCoreApplication::instance()->removeTranslator(&translator); +} + void tst_QScriptEngine::functionScopes() { QScriptEngine eng; diff --git a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp index c5e4954..6b49858 100644 --- a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp +++ b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp @@ -50,24 +50,11 @@ #include <qmenu.h> #include <qplaintextedit.h> #include <qtoolbar.h> +#include "../../shared/util.h" //TESTED_CLASS= //TESTED_FILES= -// Will try to wait for the condition while allowing event processing -#define QTRY_COMPARE(__expr, __expected) \ - do { \ - const int __step = 50; \ - const int __timeout = 5000; \ - if ((__expr) != (__expected)) { \ - QTest::qWait(0); \ - } \ - for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ - QTest::qWait(__step); \ - } \ - QCOMPARE(__expr, __expected); \ - } while(0) - // Can't use QTest::qWait() because it causes event loop to hang on some platforms static void qsWait(int ms) { @@ -89,6 +76,9 @@ public: tst_QScriptEngineDebugger(); virtual ~tst_QScriptEngineDebugger(); +protected slots: + void recordDebuggerStateAndContinue(); + private slots: void attachAndDetach(); void action(); @@ -97,6 +87,11 @@ private slots: void debuggerSignals(); void consoleCommands(); void multithreadedDebugging(); + void autoShowStandardWindow(); + void standardWindowOwnership(); + +private: + QScriptEngineDebugger::DebuggerState m_recordedDebuggerState; }; tst_QScriptEngineDebugger::tst_QScriptEngineDebugger() @@ -107,6 +102,14 @@ tst_QScriptEngineDebugger::~tst_QScriptEngineDebugger() { } +void tst_QScriptEngineDebugger::recordDebuggerStateAndContinue() +{ + QScriptEngineDebugger *debugger = qobject_cast<QScriptEngineDebugger*>(sender()); + Q_ASSERT(debugger != 0); + m_recordedDebuggerState = debugger->state(); + debugger->action(QScriptEngineDebugger::ContinueAction)->trigger(); +} + void tst_QScriptEngineDebugger::attachAndDetach() { #if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600 @@ -784,5 +787,68 @@ void tst_QScriptEngineDebugger::multithreadedDebugging() QTRY_COMPARE(threadFinishedSpy.count(), 1); } +void tst_QScriptEngineDebugger::autoShowStandardWindow() +{ + { + QScriptEngine engine; + QScriptEngineDebugger debugger; + QCOMPARE(debugger.autoShowStandardWindow(), true); + debugger.attachTo(&engine); + QObject::connect(&debugger, SIGNAL(evaluationSuspended()), + debugger.action(QScriptEngineDebugger::ContinueAction), + SLOT(trigger())); + engine.evaluate("debugger"); + QTRY_VERIFY(debugger.standardWindow()->isVisible()); + + debugger.setAutoShowStandardWindow(true); + QCOMPARE(debugger.autoShowStandardWindow(), true); + + debugger.setAutoShowStandardWindow(false); + QCOMPARE(debugger.autoShowStandardWindow(), false); + + debugger.setAutoShowStandardWindow(true); + QCOMPARE(debugger.autoShowStandardWindow(), true); + + debugger.standardWindow()->hide(); + + engine.evaluate("debugger"); + QTRY_VERIFY(debugger.standardWindow()->isVisible()); + } + + { + QScriptEngine engine; + QScriptEngineDebugger debugger; + debugger.setAutoShowStandardWindow(false); + debugger.attachTo(&engine); + QObject::connect(&debugger, SIGNAL(evaluationSuspended()), + debugger.action(QScriptEngineDebugger::ContinueAction), + SLOT(trigger())); + QSignalSpy evaluationResumedSpy(&debugger, SIGNAL(evaluationResumed())); + engine.evaluate("debugger"); + QTRY_COMPARE(evaluationResumedSpy.count(), 1); + QVERIFY(!debugger.standardWindow()->isVisible()); + } +} + +void tst_QScriptEngineDebugger::standardWindowOwnership() +{ + QScriptEngine engine; + QPointer<QMainWindow> win; + { + QScriptEngineDebugger debugger; + win = debugger.standardWindow(); + } + QVERIFY(win == 0); + + // Reparent the window. + QWidget widget; + { + QScriptEngineDebugger debugger; + win = debugger.standardWindow(); + win->setParent(&widget); + } + QVERIFY(win != 0); +} + QTEST_MAIN(tst_QScriptEngineDebugger) #include "tst_qscriptenginedebugger.moc" diff --git a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp index 1562118..29934d5 100644 --- a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp +++ b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp @@ -528,6 +528,20 @@ protected slots: private slots: void registeredTypes(); void getSetStaticProperty(); + void getSetStaticProperty_propertyFlags(); + void getSetStaticProperty_changeInCpp(); + void getSetStaticProperty_changeInJS(); + void getSetStaticProperty_compatibleVariantTypes(); + void getSetStaticProperty_conversion(); + void getSetStaticProperty_delete(); + void getSetStaticProperty_nonScriptable(); + void getSetStaticProperty_writeOnly(); + void getSetStaticProperty_readOnly(); + void getSetStaticProperty_enum(); + void getSetStaticProperty_qflags(); + void getSetStaticProperty_pointerDeref(); + void getSetStaticProperty_customGetterSetter(); + void getSetStaticProperty_methodPersistence(); void getSetDynamicProperty(); void getSetChildren(); void callQtInvokable(); @@ -655,7 +669,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() QCOMPARE(m_engine->evaluate("myObject.stringListProperty[1]").isString(), true); QCOMPARE(m_engine->evaluate("myObject.stringListProperty[1]").toString(), QLatin1String("zag")); +} +void tst_QScriptExtQObject::getSetStaticProperty_propertyFlags() +{ // default flags for "normal" properties { QScriptValue mobj = m_engine->globalObject().property("myObject"); @@ -677,7 +694,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() QVERIFY(!(mobj.propertyFlags("mySlot()") & QScriptValue::SkipInEnumeration)); QVERIFY(mobj.propertyFlags("mySlot()") & QScriptValue::QObjectMember); } +} +void tst_QScriptExtQObject::getSetStaticProperty_changeInCpp() +{ // property change in C++ should be reflected in script m_myObject->setIntProperty(456); QCOMPARE(m_engine->evaluate("myObject.intProperty") @@ -701,7 +721,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() m_myObject->setStringProperty(QLatin1String("zab")); QCOMPARE(m_engine->evaluate("myObject.stringProperty") .equals(QScriptValue(m_engine, QLatin1String("zab"))), true); +} +void tst_QScriptExtQObject::getSetStaticProperty_changeInJS() +{ // property change in script should be reflected in C++ QCOMPARE(m_engine->evaluate("myObject.intProperty = 123") .strictlyEquals(QScriptValue(m_engine, 123)), true); @@ -784,7 +807,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() << QLatin1String("two") << QLatin1String("true")); } +} +void tst_QScriptExtQObject::getSetStaticProperty_compatibleVariantTypes() +{ // test setting properties where we can't convert the type natively but where the // types happen to be compatible variant types already { @@ -803,7 +829,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() mobj.setProperty("propWithCustomType", m_engine->newVariant(qVariantFromValue(t))); QVERIFY(m_myObject->propWithCustomType().string == t.string); } +} +void tst_QScriptExtQObject::getSetStaticProperty_conversion() +{ // test that we do value conversion if necessary when setting properties { QScriptValue br = m_engine->evaluate("myObject.brushProperty"); @@ -823,28 +852,41 @@ void tst_QScriptExtQObject::getSetStaticProperty() m_engine->globalObject().setProperty("myColor", QScriptValue()); } +} +void tst_QScriptExtQObject::getSetStaticProperty_delete() +{ // try to delete QCOMPARE(m_engine->evaluate("delete myObject.intProperty").toBoolean(), false); QCOMPARE(m_engine->evaluate("myObject.intProperty").toNumber(), 123.0); + m_myObject->setVariantProperty(42); QCOMPARE(m_engine->evaluate("delete myObject.variantProperty").toBoolean(), false); QCOMPARE(m_engine->evaluate("myObject.variantProperty").toNumber(), 42.0); +} +void tst_QScriptExtQObject::getSetStaticProperty_nonScriptable() +{ // non-scriptable property QCOMPARE(m_myObject->hiddenProperty(), 456.0); QCOMPARE(m_engine->evaluate("myObject.hiddenProperty").isUndefined(), true); QCOMPARE(m_engine->evaluate("myObject.hiddenProperty = 123;" "myObject.hiddenProperty").toInt32(), 123); QCOMPARE(m_myObject->hiddenProperty(), 456.0); +} +void tst_QScriptExtQObject::getSetStaticProperty_writeOnly() +{ // write-only property QCOMPARE(m_myObject->writeOnlyProperty(), 789); QCOMPARE(m_engine->evaluate("myObject.writeOnlyProperty").isUndefined(), true); QCOMPARE(m_engine->evaluate("myObject.writeOnlyProperty = 123;" "myObject.writeOnlyProperty").isUndefined(), true); QCOMPARE(m_myObject->writeOnlyProperty(), 123); +} +void tst_QScriptExtQObject::getSetStaticProperty_readOnly() +{ // read-only property QCOMPARE(m_myObject->readOnlyProperty(), 987); QCOMPARE(m_engine->evaluate("myObject.readOnlyProperty").toInt32(), 987); @@ -856,7 +898,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() QCOMPARE(mobj.propertyFlags("readOnlyProperty") & QScriptValue::ReadOnly, QScriptValue::ReadOnly); } +} +void tst_QScriptExtQObject::getSetStaticProperty_enum() +{ // enum property QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy); { @@ -881,7 +926,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() QCOMPARE(m_myObject->enumProperty(), MyQObject::BazPolicy); m_engine->evaluate("myObject.enumProperty = 'nada'"); QCOMPARE(m_myObject->enumProperty(), (MyQObject::Policy)-1); +} +void tst_QScriptExtQObject::getSetStaticProperty_qflags() +{ // flags property QCOMPARE(m_myObject->flagsProperty(), MyQObject::FooAbility); { @@ -900,7 +948,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() m_engine->evaluate("myObject.flagsProperty = 'ScoobyDoo'"); // ### ouch! Shouldn't QMetaProperty::write() rather not change the value...? QCOMPARE(m_myObject->flagsProperty(), (MyQObject::Ability)-1); +} +void tst_QScriptExtQObject::getSetStaticProperty_pointerDeref() +{ // auto-dereferencing of pointers { QBrush b = QColor(0xCA, 0xFE, 0xBA, 0xBE); @@ -920,7 +971,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() } m_engine->globalObject().setProperty("brushPointer", QScriptValue()); } +} +void tst_QScriptExtQObject::getSetStaticProperty_customGetterSetter() +{ // install custom property getter+setter { QScriptValue mobj = m_engine->globalObject().property("myObject"); @@ -930,7 +984,10 @@ void tst_QScriptExtQObject::getSetStaticProperty() mobj.setProperty("intProperty", 321); QCOMPARE(mobj.property("intProperty").toInt32(), 321); } +} +void tst_QScriptExtQObject::getSetStaticProperty_methodPersistence() +{ // method properties are persistent { QScriptValue slot = m_engine->evaluate("myObject.mySlot"); diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index be51cf2..528b20e 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp @@ -2332,6 +2332,54 @@ void tst_QScriptValue::getSetPrototype_twoEngines() } +void tst_QScriptValue::getSetPrototype_null() +{ + QScriptEngine eng; + QScriptValue object = eng.newObject(); + object.setPrototype(QScriptValue(QScriptValue::NullValue)); + QVERIFY(object.prototype().isNull()); + + QScriptValue newProto = eng.newObject(); + object.setPrototype(newProto); + QVERIFY(object.prototype().equals(newProto)); + + object.setPrototype(QScriptValue(&eng, QScriptValue::NullValue)); + QVERIFY(object.prototype().isNull()); +} + +void tst_QScriptValue::getSetPrototype_notObjectOrNull() +{ + QScriptEngine eng; + QScriptValue object = eng.newObject(); + QScriptValue originalProto = object.prototype(); + + QEXPECT_FAIL("", "QTBUG-15154: QScriptValue::setPrototype() allows a non-Object value to be set as prototype", Abort); + + // bool + object.setPrototype(true); + QVERIFY(object.prototype().equals(originalProto)); + object.setPrototype(QScriptValue(&eng, true)); + QVERIFY(object.prototype().equals(originalProto)); + + // number + object.setPrototype(123); + QVERIFY(object.prototype().equals(originalProto)); + object.setPrototype(QScriptValue(&eng, 123)); + QVERIFY(object.prototype().equals(originalProto)); + + // string + object.setPrototype("foo"); + QVERIFY(object.prototype().equals(originalProto)); + object.setPrototype(QScriptValue(&eng, "foo")); + QVERIFY(object.prototype().equals(originalProto)); + + // undefined + object.setPrototype(QScriptValue(QScriptValue::UndefinedValue)); + QVERIFY(object.prototype().equals(originalProto)); + object.setPrototype(QScriptValue(&eng, QScriptValue::UndefinedValue)); + QVERIFY(object.prototype().equals(originalProto)); +} + void tst_QScriptValue::getSetPrototype() { QScriptEngine eng; diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.h b/tests/auto/qscriptvalue/tst_qscriptvalue.h index 45a109e..c6b2202 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.h +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.h @@ -115,6 +115,8 @@ private slots: void getSetPrototype_eval(); void getSetPrototype_invalidPrototype(); void getSetPrototype_twoEngines(); + void getSetPrototype_null(); + void getSetPrototype_notObjectOrNull(); void getSetPrototype(); void getSetScope(); void getSetProperty_HooliganTask162051(); diff --git a/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp b/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp index e68db06..62f3c2a 100644 --- a/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp +++ b/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp @@ -309,6 +309,9 @@ private slots: void qobjectSignalHandler(); void customTypeSignalHandler(); + void emitSignal_data(); + void emitSignal(); + void readButtonMetaProperty_data(); void readButtonMetaProperty(); @@ -948,6 +951,31 @@ void tst_QScriptQObject::customTypeSignalHandler() } } +void tst_QScriptQObject::emitSignal_data() +{ + QTest::addColumn<QString>("propertyName"); + QTest::addColumn<QString>("arguments"); + + QTest::newRow("voidSignal()") << "voidSignal" << ""; + + QTest::newRow("boolSignal(true)") << "boolSignal" << "true"; + QTest::newRow("intSignal(123)") << "intSignal" << "123"; + QTest::newRow("doubleSignal(123)") << "doubleSignal" << "123"; + QTest::newRow("stringSignal('hello')") << "stringSignal" << "'hello'"; + QTest::newRow("variantSignal(123)") << "variantSignal" << "123"; + QTest::newRow("qobjectSignal(this)") << "qobjectSignal" << "this"; // assumes 'this' is a QObject +} + +void tst_QScriptQObject::emitSignal() +{ + QFETCH(QString, propertyName); + QFETCH(QString, arguments); + + QScriptEngine engine; + SignalTestObject testObject; + callMethodHelper(engine, &testObject, propertyName, arguments); +} + void tst_QScriptQObject::readButtonMetaProperty_data() { readMetaProperty_dataHelper(&QPushButton::staticMetaObject); diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index 540ffa9..d1e2c60 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -1543,8 +1543,72 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer, return true; } + /*! - */ + Returns true if the node \a n1 is less than node \a n2. + The comparison is performed by comparing properties of the nodes in order + of increasing complexity. +*/ +bool compareNodes(const Node *n1, const Node *n2) +{ + // Private nodes can occur in any order since they won't normally be + // written to the index. + if (n1->access() == Node::Private && n2->access() == Node::Private) + return true; + + if (n1->location().filePath() < n2->location().filePath()) + return true; + else if (n1->location().filePath() > n2->location().filePath()) + return false; + + if (n1->type() < n2->type()) + return true; + else if (n1->type() > n2->type()) + return false; + + if (n1->name() < n2->name()) + return true; + else if (n1->name() > n2->name()) + return false; + + if (n1->access() < n2->access()) + return true; + else if (n1->access() > n2->access()) + return false; + + if (n1->type() == Node::Function && n2->type() == Node::Function) { + const FunctionNode *f1 = static_cast<const FunctionNode *>(n1); + const FunctionNode *f2 = static_cast<const FunctionNode *>(n2); + + if (f1->isConst() < f2->isConst()) + return true; + else if (f1->isConst() > f2->isConst()) + return false; + + if (f1->signature() < f2->signature()) + return true; + else if (f1->signature() > f2->signature()) + return false; + } + + if (n1->type() == Node::Fake && n2->type() == Node::Fake) { + const FakeNode *f1 = static_cast<const FakeNode *>(n1); + const FakeNode *f2 = static_cast<const FakeNode *>(n2); + if (f1->fullTitle() < f2->fullTitle()) + return true; + else if (f1->fullTitle() > f2->fullTitle()) + return false; + } + + return false; +} + +/*! + Generate index sections for the child nodes of the given \a node + using the \a writer specified. If \a generateInternalNodes is true, + nodes marked as internal will be included in the index; otherwise, + they will be omitted. +*/ void Tree::generateIndexSections(QXmlStreamWriter &writer, const Node *node, bool generateInternalNodes) const @@ -1554,7 +1618,10 @@ void Tree::generateIndexSections(QXmlStreamWriter &writer, if (node->isInnerNode()) { const InnerNode *inner = static_cast<const InnerNode *>(node); - foreach (const Node *child, inner->childNodes()) { + NodeList cnodes = inner->childNodes(); + qSort(cnodes.begin(), cnodes.end(), compareNodes); + + foreach (const Node *child, cnodes) { /* Don't generate anything for a QML property group node. It is just a place holder for a collection of QML property |