1212#include " include/setSpiderMonkeyException.hh"
1313
1414#include " include/ExceptionType.hh"
15+ #include " include/StrType.hh"
1516
1617#include < jsapi.h>
1718#include < js/Exception.h>
@@ -26,7 +27,7 @@ ExceptionType::ExceptionType(JSContext *cx, JS::HandleObject error) {
2627 // Convert the JS Error object to a Python string
2728 JS::RootedValue errValue (cx, JS::ObjectValue (*error)); // err
2829 JS::RootedObject errStack (cx, JS::ExceptionStackOrNull (error)); // err.stack
29- PyObject *errStr = getExceptionString (cx, JS::ExceptionStack (cx, errValue, errStack));
30+ PyObject *errStr = getExceptionString (cx, JS::ExceptionStack (cx, errValue, errStack), true );
3031
3132 // Construct a new SpiderMonkeyError python object
3233 // pyObject = SpiderMonkeyError(errStr)
@@ -78,6 +79,25 @@ tb_print_line_repeated(_PyUnicodeWriter *writer, long cnt)
7879JSObject *ExceptionType::toJsError (JSContext *cx, PyObject *exceptionValue, PyObject *traceBack) {
7980 assert (exceptionValue != NULL );
8081
82+ // Gather JS context
83+ JS_ReportErrorASCII (cx, " " ); // throw JS error and gather all details
84+
85+ JS::ExceptionStack exceptionStack (cx);
86+ if (!JS::GetPendingExceptionStack (cx, &exceptionStack)) {
87+ return NULL ;
88+ }
89+ JS_ClearPendingException (cx);
90+
91+ std::stringstream stackStream;
92+ JS::RootedObject stackObj (cx, exceptionStack.stack ());
93+ if (stackObj.get ()) {
94+ JS::RootedString stackStr (cx);
95+ JS::BuildStackString (cx, nullptr , stackObj, &stackStr, 2 , js::StackFormat::SpiderMonkey);
96+ stackStream << " JS Stack Trace:\n " << StrType (cx, stackStr).getValue ();
97+ }
98+
99+
100+ // Gather Python context
81101 PyObject *pyErrType = PyObject_Type (exceptionValue);
82102 const char *pyErrTypeName = _PyType_Name ((PyTypeObject *)pyErrType);
83103
@@ -235,12 +255,12 @@ JSObject *ExceptionType::toJsError(JSContext *cx, PyObject *exceptionValue, PyOb
235255 {
236256 std::stringstream msgStream;
237257 msgStream << " Python " << pyErrTypeName << " : " << PyUnicode_AsUTF8 (pyErrMsg) << " \n " << PyUnicode_AsUTF8 (_PyUnicodeWriter_Finish (&writer));
238- std::string msg = msgStream .str ();
258+ msgStream << stackStream .str ();
239259
240260 JS::RootedValue rval (cx);
241261 JS::RootedString filename (cx, JS_NewStringCopyZ (cx, PyUnicode_AsUTF8 (fileName)));
242- JS::RootedString message (cx, JS_NewStringCopyZ (cx, msg .c_str ()));
243- // TODO stack argument cannot be passed in as a string anymore (deprecated), and could not find a proper example using the new argument type
262+ JS::RootedString message (cx, JS_NewStringCopyZ (cx, msgStream. str () .c_str ()));
263+ // stack argument cannot be passed in as a string anymore (deprecated), and could not find a proper example using the new argument type
244264 if (!JS::CreateError (cx, JSExnType::JSEXN_ERR, nullptr , filename, lineno, 0 , nullptr , message, JS::NothingHandleValue, &rval)) {
245265 return NULL ;
246266 }
@@ -256,15 +276,22 @@ JSObject *ExceptionType::toJsError(JSContext *cx, PyObject *exceptionValue, PyOb
256276 Py_XDECREF (code);
257277 }
258278
279+ // gather additional JS context details
280+ JS::ErrorReportBuilder reportBuilder (cx);
281+ if (!reportBuilder.init (cx, exceptionStack, JS::ErrorReportBuilder::WithSideEffects)) {
282+ return NULL ;
283+ }
284+ JSErrorReport *errorReport = reportBuilder.report ();
285+
259286 std::stringstream msgStream;
260287 msgStream << " Python " << pyErrTypeName << " : " << PyUnicode_AsUTF8 (pyErrMsg);
261- std::string msg = msgStream .str ();
288+ msgStream << stackStream .str ();
262289
263290 JS::RootedValue rval (cx);
264- JS::RootedObject stack (cx);
265- JS::RootedString filename (cx, JS_NewStringCopyZ (cx, " [python code] " ));
266- JS::RootedString message (cx, JS_NewStringCopyZ (cx, msg. c_str ()));
267- if (!JS::CreateError (cx, JSExnType::JSEXN_ERR, nullptr , filename, 0 , 0 , nullptr , message, JS::NothingHandleValue, &rval)) {
291+ JS::RootedString filename (cx, JS_NewStringCopyZ (cx, " " )); // cannot be null or omitted, but is overriden by the errorReport
292+ JS::RootedString message (cx, JS_NewStringCopyZ (cx, msgStream. str (). c_str () ));
293+ // filename cannot be null
294+ if (!JS::CreateError (cx, JSExnType::JSEXN_ERR, nullptr , filename, 0 , 0 , errorReport , message, JS::NothingHandleValue, &rval)) {
268295 return NULL ;
269296 }
270297
0 commit comments