aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsapi
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-08-29 14:16:39 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2020-09-02 16:03:57 +0200
commit0056a8d9e10e83157c3974ec1475ac1f96fb9cde (patch)
tree7dc0eb5c2d6b4f0d01c63394b38a51ba0dccece7 /src/qml/jsapi
parentf2627a6e46a64cd2ed4eb1e14f2fb5c54671be4f (diff)
QJSEngine: provide a way to check if an exception was thrown
[ChangeLog][QML][QJSEngine] QJSEngine::evaluate gained an optional stackTrace parameter. It can be used to check if the returned QJSValue comes from an uncaught exception, and to retrieve the backtrace of the execution leading to the error. Fixes: QTBUG-54925 Change-Id: I2b5ada1f0c33c335b4b9d0d1268e70ca63a1fad1 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsapi')
-rw-r--r--src/qml/jsapi/qjsengine.cpp32
-rw-r--r--src/qml/jsapi/qjsengine.h2
2 files changed, 28 insertions, 6 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 15b7682ae2..6f10495610 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -485,12 +485,21 @@ static QUrl urlForFileName(const QString &fileName)
the file name is accessible through the "fileName" property if it is
provided with this function.
+ \a stackTrace is used to report whether an uncaught exception was
+ thrown. If you pass a non-null pointer to a boolean to it, it will set
+ it to list of "stackframe messages" if the script threw an unhandled
+ exception, or an empty list otherwise. A stackframe message has the format
+ function name:line number:column:file name
+ \note In some cases, e.g. for native functions, function name and file name
+ can be empty and line number and column can be -1.
+
\note If an exception was thrown and the exception value is not an
Error instance (i.e., QJSValue::isError() returns \c false), the
- exception value will still be returned, but there is currently no
- API for detecting that an exception did occur in this case.
+ exception value will still be returned. Use \a stackTrace to
+ distinguish whether the value was a normal or an exceptional return
+ value.
*/
-QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
+QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber, QStringList *exceptionStackTrace)
{
QV4::ExecutionEngine *v4 = m_v4Engine;
QV4::Scope scope(v4);
@@ -506,8 +515,21 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
script.parse();
if (!scope.engine->hasException)
result = script.run();
- if (scope.engine->hasException)
- result = v4->catchException();
+ if (exceptionStackTrace)
+ exceptionStackTrace->clear();
+ if (scope.engine->hasException) {
+ QV4::StackTrace trace;
+ result = v4->catchException(&trace);
+ if (exceptionStackTrace) {
+ for (auto &&frame: trace)
+ exceptionStackTrace->push_back(QString::fromLatin1("%1:%2:%3:%4").arg(
+ frame.function,
+ QString::number(frame.line),
+ QString::number(frame.column),
+ frame.source)
+ );
+ }
+ }
if (v4->isInterrupted.loadAcquire())
result = v4->newErrorObject(QStringLiteral("Interrupted"));
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index a025ce991d..775f9e658a 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -68,7 +68,7 @@ public:
QJSValue globalObject() const;
- QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
+ QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1, QStringList *exceptionStackTrace = nullptr);
QJSValue importModule(const QString &fileName);