From 53273dad5055e64208bbc7214532f707b8fa1b92 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Mon, 20 Jan 2014 19:09:57 +0100 Subject: [PATCH] Check JS callback errors. Fixes #9 Thanks to Osmo Salomaa for the original report and test case. --- src/qpython.cpp | 12 +++++++++- tests/test_errors/README | 6 +++++ tests/test_errors/test_errors.py | 11 +++++++++ tests/test_errors/test_errors.qml | 40 +++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/test_errors/README create mode 100644 tests/test_errors/test_errors.py create mode 100644 tests/test_errors/test_errors.qml diff --git a/src/qpython.cpp b/src/qpython.cpp index 48e3a55..72c6885 100644 --- a/src/qpython.cpp +++ b/src/qpython.cpp @@ -120,7 +120,17 @@ QPython::receive(QVariant variant) for (int i=1; itoScriptValue(list[i]); } - callback.call(args); + QJSValue result = callback.call(args); + if (result.isError()) { + // Ideally we would throw the error back to Python (so that the + // pyotherside.send() method fails, as this is where the call + // originated). We can't do this, because the pyotherside.send() + // call is asynchronous (it returns before we call into JS), so do + // the next best thing and report the error to our error handler in + // QML instead. + emit error(QString("pyotherside.send() failed handler: %1") + .arg(result.toString())); + } } else { // Default action emit received(variant); diff --git a/tests/test_errors/README b/tests/test_errors/README new file mode 100644 index 0000000..c6a5425 --- /dev/null +++ b/tests/test_errors/README @@ -0,0 +1,6 @@ +Test if JS errors from pyotherside.send() are propagated to the PyOtherSide +error handler. Thanks to Osmo Salomaa for the original report and test case. + +---- +https://github.com/thp/pyotherside/issues/9 +https://gist.github.com/otsaloma/8258322 diff --git a/tests/test_errors/test_errors.py b/tests/test_errors/test_errors.py new file mode 100644 index 0000000..c8c5d4c --- /dev/null +++ b/tests/test_errors/test_errors.py @@ -0,0 +1,11 @@ +import pyotherside +import threading +import time + +def run(): + while True: + pyotherside.send("test-errors") + time.sleep(3) + +thread = threading.Thread(target=run) +thread.start() diff --git a/tests/test_errors/test_errors.qml b/tests/test_errors/test_errors.qml new file mode 100644 index 0000000..7652177 --- /dev/null +++ b/tests/test_errors/test_errors.qml @@ -0,0 +1,40 @@ +import QtQuick 2.0 +import io.thp.pyotherside 1.0 + +Rectangle { + id: page + width: 300 + height: 300 + + Component.onCompleted: { + py.addImportPath(Qt.resolvedUrl('.').substr('file://'.length)); + py.setHandler("test-errors", page.testErrors); + py.importModule("test_errors", null); + } + + Python { + id: py + + onError: { + console.log("PYTHON ERROR: " + traceback); + msg.text += '\n' + traceback; + } + } + + Text { + id: msg + anchors { + top: parent.top + left: parent.left + right: parent.right + } + text: "Testing (you should see errors appearing here)..." + wrapMode: Text.Wrap + } + + function testErrors() { + console.log("starting"); + page.nonexistentMethod(); + console.log("finished"); + } +}