# HG changeset patch # User Atul Varma # Date 1250577740 25200 # Node ID 856ca7a139e4cc79a1fa88f8faf1fdeae9af5126 # Parent d30576edf797af1676510e15967dd8156d975b40 Pymonkey errors raised as a result of JS exceptions now contain both the string representation and the original Python-wrapped JS object that was thrown (i.e., the exception). diff -r d30576edf797 -r 856ca7a139e4 src/utils.cpp --- a/src/utils.cpp Mon Aug 17 22:36:42 2009 -0700 +++ b/src/utils.cpp Mon Aug 17 23:42:20 2009 -0700 @@ -233,25 +233,35 @@ jsval val; if (JS_GetPendingException(context->cx, &val)) { + PyObject *pyStr = NULL; + PyObject *tuple = NULL; PyObject *obj = PYM_jsvalToPyObject(context, val); - if (obj) { - PyErr_SetObject(PYM_error, obj); - Py_DECREF(obj); - } else { + if (obj == NULL) { PyErr_Clear(); + obj = Py_None; + Py_INCREF(obj); + } - JSString *str = NULL; + JSString *str = NULL; + + Py_BEGIN_ALLOW_THREADS; + str = JS_ValueToString(context->cx, val); + Py_END_ALLOW_THREADS; - Py_BEGIN_ALLOW_THREADS; - str = JS_ValueToString(context->cx, val); - Py_END_ALLOW_THREADS; + if (str != NULL) + pyStr = PYM_jsvalToPyObject(context, STRING_TO_JSVAL(str)); + else + // TODO: Is there an exception in JS-land we should clear? + pyStr = PyString_FromString(""); - if (str != NULL) { - const char *chars = JS_GetStringBytes(str); - PyErr_SetString(PYM_error, chars); - } else - PyErr_SetString(PYM_error, "JS exception occurred"); + if (pyStr) { + tuple = Py_BuildValue("(OO)", obj, pyStr); + if (tuple) + PyErr_SetObject(PYM_error, tuple); } + Py_DECREF(obj); + Py_XDECREF(pyStr); + Py_XDECREF(tuple); } else PyErr_SetString(PYM_error, "JS_GetPendingException() failed"); } diff -r d30576edf797 -r 856ca7a139e4 tests/test_pymonkey.py --- a/tests/test_pymonkey.py Mon Aug 17 22:36:42 2009 -0700 +++ b/tests/test_pymonkey.py Mon Aug 17 23:42:20 2009 -0700 @@ -31,6 +31,11 @@ was_raised = True self.assertTrue(was_raised) + def testErrorsRaisedIncludeStrings(self): + self.assertRaises(pymonkey.error, self._evaljs, 'boop()') + self.assertEqual(self.last_exception.args[1], + u'ReferenceError: boop is not defined') + def testThreadSafetyExceptionIsRaised(self): stuff = {} def make_runtime():