1818#include < codecvt>
1919#include < locale>
2020
21- PyObject *getExceptionString (JSContext *cx, const JS::ExceptionStack &exceptionStack) {
21+ PyObject *getExceptionString (JSContext *cx, const JS::ExceptionStack &exceptionStack, bool printStack ) {
2222 JS::ErrorReportBuilder reportBuilder (cx);
2323 if (!reportBuilder.init (cx, exceptionStack, JS::ErrorReportBuilder::WithSideEffects /* may call the `toString` method if an object is thrown */ )) {
2424 return PyUnicode_FromString (" Spidermonkey set an exception, but could not initialize the error report." );
@@ -56,12 +56,13 @@ PyObject *getExceptionString(JSContext *cx, const JS::ExceptionStack &exceptionS
5656 // print out the SpiderMonkey error message
5757 outStrStream << reportBuilder.toStringResult ().c_str () << " \n " ;
5858
59-
60- JS::RootedObject stackObj (cx, exceptionStack.stack ());
61- if (stackObj.get ()) {
62- JS::RootedString stackStr (cx);
63- BuildStackString (cx, nullptr , stackObj, &stackStr, /* indent */ 2 , js::StackFormat::SpiderMonkey);
64- outStrStream << " Stack Trace: \n " << StrType (cx, stackStr).getValue ();
59+ if (printStack) {
60+ JS::RootedObject stackObj (cx, exceptionStack.stack ());
61+ if (stackObj.get ()) {
62+ JS::RootedString stackStr (cx);
63+ BuildStackString (cx, nullptr , stackObj, &stackStr, /* indent */ 2 , js::StackFormat::SpiderMonkey);
64+ outStrStream << " Stack Trace: \n " << StrType (cx, stackStr).getValue ();
65+ }
6566 }
6667
6768 return PyUnicode_FromString (outStrStream.str ().c_str ());
@@ -80,11 +81,35 @@ void setSpiderMonkeyException(JSContext *cx) {
8081 PyErr_SetString (SpiderMonkeyError, " Spidermonkey set an exception, but was unable to retrieve it." );
8182 return ;
8283 }
84+
85+ // check if it is a Python Exception and already has a stack trace
86+ bool printStack;
87+
88+ JS::Rooted<JS::Value> exn (cx);
89+ JS_GetPendingException (cx, &exn);
90+ if (exn.isObject ()) {
91+ JS::RootedObject exnObj (cx, &exn.toObject ());
92+ JS::RootedValue tmp (cx);
93+ if (!JS_GetProperty (cx, exnObj, " message" , &tmp)) {
94+ printStack = true ;
95+ }
96+ else if (tmp.isString ()) {
97+ JS::RootedString rootedStr (cx, tmp.toString ());
98+ printStack = strstr (JS_EncodeStringToUTF8 (cx, rootedStr).get (), " JS Stack Trace" ) == NULL ;
99+ }
100+ else {
101+ printStack = true ;
102+ }
103+ }
104+ else {
105+ printStack = true ;
106+ }
107+
83108 JS_ClearPendingException (cx);
84109
85110 // `PyErr_SetString` uses `PyErr_SetObject` with `PyUnicode_FromString` under the hood
86111 // see https://github.com/python/cpython/blob/3.9/Python/errors.c#L234-L236
87- PyObject *errStr = getExceptionString (cx, exceptionStack);
112+ PyObject *errStr = getExceptionString (cx, exceptionStack, printStack );
88113 PyErr_SetObject (SpiderMonkeyError, errStr);
89114 Py_XDECREF (errStr);
90115}
0 commit comments