From 610508fcbf95b16567a17f53fd370f9b0ae3505b Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 16 May 2023 17:14:03 +0200 Subject: Properly handle non-string exceptions Fixes: QBS-1734 Change-Id: If7901dc698fdd5ee44021a3b92cf28295123eccc Reviewed-by: Ivan Komissarov --- src/lib/corelib/tools/scripttools.cpp | 22 ++++++++++++++++++--- tests/auto/language/testdata/throw.qbs | 16 ++++++++++++++++ tests/auto/language/tst_language.cpp | 35 ++++++++++++++++++++++++++++++++++ tests/auto/language/tst_language.h | 2 ++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 tests/auto/language/testdata/throw.qbs diff --git a/src/lib/corelib/tools/scripttools.cpp b/src/lib/corelib/tools/scripttools.cpp index 109b74486..cf2d1424f 100644 --- a/src/lib/corelib/tools/scripttools.cpp +++ b/src/lib/corelib/tools/scripttools.cpp @@ -43,6 +43,9 @@ #include #include +#include +#include +#include namespace qbs { namespace Internal { @@ -89,9 +92,22 @@ JsException::~JsException() { JS_FreeValue(m_ctx, m_exception); } QString JsException::message() const { - if (JS_IsString(m_exception)) - return getJsString(m_ctx, m_exception); - return getJsStringProperty(m_ctx, m_exception, QStringLiteral("message")); + if (JS_IsError(m_ctx, m_exception)) + return getJsStringProperty(m_ctx, m_exception, QStringLiteral("message")); + const QVariant v = getJsVariant(m_ctx, m_exception); + switch (static_cast(v.userType())) { + case QMetaType::QVariantMap: + return QString::fromUtf8(QJsonDocument(QJsonObject::fromVariantMap(v.toMap())) + .toJson(QJsonDocument::Indented)); + case QMetaType::QStringList: + return QString::fromUtf8(QJsonDocument(QJsonArray::fromStringList(v.toStringList())) + .toJson(QJsonDocument::Indented)); + case QMetaType::QVariantList: + return QString::fromUtf8(QJsonDocument(QJsonArray::fromVariantList(v.toList())) + .toJson(QJsonDocument::Indented)); + default: + return v.toString(); + } } const QStringList JsException::stackTrace() const diff --git a/tests/auto/language/testdata/throw.qbs b/tests/auto/language/testdata/throw.qbs new file mode 100644 index 000000000..e9a97efb5 --- /dev/null +++ b/tests/auto/language/testdata/throw.qbs @@ -0,0 +1,16 @@ +Project { + property string throwType + property bool dummy: { + if (throwType === "bool") + throw true; + if (throwType === "int") + throw 43; + if (throwType === "string") + throw "an error"; + if (throwType === "list") + throw ["an", "error"]; + if (throwType === "object") + throw { result: "crash", reason: "overheating" }; + throw "type missing"; + } +} diff --git a/tests/auto/language/tst_language.cpp b/tests/auto/language/tst_language.cpp index 50269a7d7..9045442c9 100644 --- a/tests/auto/language/tst_language.cpp +++ b/tests/auto/language/tst_language.cpp @@ -65,6 +65,7 @@ #include #include +#include #include #include @@ -371,6 +372,40 @@ void TestLanguage::rfc1034Identifier() QCOMPARE(exceptionCaught, false); } +void TestLanguage::throwThings_data() +{ + QTest::addColumn("type"); + QTest::addColumn("result"); + QTest::addRow("bool") << "bool" << "true"; + QTest::addRow("int") << "int" << "43"; + QTest::addRow("string") << "string" << "an error"; + QTest::addRow("list") << "list" << R"([ + "an", + "error" +])"; + QTest::addRow("object") << "object" << R"({ + "reason": "overheating", + "result": "crash" +})"; +} + +void TestLanguage::throwThings() +{ + QFETCH(QString, type); + QFETCH(QString, result); + bool exceptionCaught = false; + try { + SetupProjectParameters params = defaultParameters; + params.setProjectFilePath(testProject("throw.qbs")); + params.setOverriddenValues({{"project.throwType", type}}); + loader->loadProject(params); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + QVERIFY2(e.toString().contains(result), qPrintable(e.toString())); + } + QVERIFY(exceptionCaught); +} + void TestLanguage::conditionalDepends() { bool exceptionCaught = false; diff --git a/tests/auto/language/tst_language.h b/tests/auto/language/tst_language.h index 4fe2752e4..e72259a0f 100644 --- a/tests/auto/language/tst_language.h +++ b/tests/auto/language/tst_language.h @@ -177,6 +177,8 @@ private slots: void qualifiedId(); void recursiveProductDependencies(); void rfc1034Identifier(); + void throwThings_data(); + void throwThings(); void useInternalProfile(); void versionCompare(); void wildcards_data(); -- cgit v1.2.1