changeset 120:856ca7a139e4

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).
author Atul Varma <varmaa@toolness.com>
date Mon, 17 Aug 2009 23:42:20 -0700
parents d30576edf797
children edce6af83ee2
files src/utils.cpp tests/test_pymonkey.py
diffstat 2 files changed, 28 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- 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("<string conversion failed>");
 
-      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");
 }
--- 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():