@@ -23,14 +23,20 @@ NativeScriptException::NativeScriptException(const string& message)
2323 m_javascriptException(nullptr ), m_javaException(JniLocalRef()), m_message(message) {
2424}
2525
26+ NativeScriptException::NativeScriptException (const string& message, const string& stackTrace)
27+ :
28+ m_javascriptException(nullptr ), m_javaException(JniLocalRef()), m_message(message), m_stackTrace(stackTrace) {
29+ }
30+
2631NativeScriptException::NativeScriptException (TryCatch& tc, const string& message)
2732 :
2833 m_javaException(JniLocalRef()) {
2934 auto isolate = Isolate::GetCurrent ();
3035 m_javascriptException = new Persistent<Value>(isolate, tc.Exception ());
31- bool isMessageEmpty = tc.Message ().IsEmpty ();
32- bool isExceptionEmpty = tc.Exception ().IsEmpty ();
33- m_message = GetFullMessage (tc, isExceptionEmpty, isMessageEmpty, message);
36+ auto ex = tc.Exception ();
37+ m_message = GetErrorMessage (tc.Message (), ex, message);
38+ m_stackTrace = GetErrorStackTrace (tc.Message ()->GetStackTrace ());
39+ m_fullMessage = GetFullMessage (tc, m_message);
3440 tc.Reset ();
3541}
3642
@@ -40,9 +46,15 @@ void NativeScriptException::ReThrowToV8() {
4046
4147 if (m_javascriptException != nullptr ) {
4248 errObj = Local<Value>::New (isolate, *m_javascriptException);
43- if (errObj->IsObject () && !m_message.empty ()) {
44- errObj.As <Object>()->Set (ArgConverter::ConvertToV8String (isolate, " fullMessage" ), ArgConverter::ConvertToV8String (isolate, m_message));
49+ if (errObj->IsObject ()) {
50+ if (!m_fullMessage.empty ()) {
51+ errObj.As <Object>()->Set (ArgConverter::ConvertToV8String (isolate, " fullMessage" ), ArgConverter::ConvertToV8String (isolate, m_fullMessage));
52+ } else if (!m_message.empty ()) {
53+ errObj.As <Object>()->Set (ArgConverter::ConvertToV8String (isolate, " fullMessage" ), ArgConverter::ConvertToV8String (isolate, m_message));
54+ }
4555 }
56+ } else if (!m_fullMessage.empty ()) {
57+ errObj = Exception::Error (ArgConverter::ConvertToV8String (isolate, m_fullMessage));
4658 } else if (!m_message.empty ()) {
4759 errObj = Exception::Error (ArgConverter::ConvertToV8String (isolate, m_message));
4860 } else if (!m_javaException.IsNull ()) {
@@ -83,22 +95,24 @@ void NativeScriptException::ReThrowToJava() {
8395 ex = (jthrowable) exObj.Move ();
8496 }
8597
98+ JniLocalRef msg (env.NewStringUTF (m_message.c_str ()));
99+ JniLocalRef stackTrace (env.NewStringUTF (m_stackTrace.c_str ()));
100+
86101 if (ex == nullptr ) {
87- JniLocalRef msg (env.NewStringUTF (m_message.c_str ()));
88- ex = static_cast <jthrowable>(env.NewObject (NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID, (jstring) msg, reinterpret_cast <jlong>(m_javascriptException)));
102+ ex = static_cast <jthrowable>(env.NewObject (NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID, (jstring) msg, (jstring)stackTrace, reinterpret_cast <jlong>(m_javascriptException)));
89103 } else {
90104 auto excClassName = objectManager->GetClassName (ex);
91105 if (excClassName != " com/tns/NativeScriptException" ) {
92- JniLocalRef msg (env.NewStringUTF (m_message.c_str ()));
93- ex = static_cast <jthrowable>(env.NewObject (NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID, (jstring) msg, ex));
106+ ex = static_cast <jthrowable>(env.NewObject (NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID, (jstring) msg, (jstring)stackTrace, ex));
94107 }
95108 }
96109 } else if (!m_message.empty ()) {
97110 JniLocalRef msg (env.NewStringUTF (m_message.c_str ()));
98- ex = static_cast <jthrowable>(env.NewObject (NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID, (jstring) msg, (jlong) 0 ));
111+ JniLocalRef stackTrace (env.NewStringUTF (m_stackTrace.c_str ()));
112+ ex = static_cast <jthrowable>(env.NewObject (NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID, (jstring) msg, (jstring)stackTrace, (jlong) 0 ));
99113 } else {
100114 JniLocalRef msg (env.NewStringUTF (" No java exception or message provided." ));
101- ex = static_cast <jthrowable>(env.NewObject (NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID, (jstring) msg, (jlong) 0 ));
115+ ex = static_cast <jthrowable>(env.NewObject (NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID, (jstring) msg, (jstring) nullptr , ( jlong) 0 ));
102116 }
103117 env.Throw (ex);
104118}
@@ -115,10 +129,10 @@ void NativeScriptException::Init() {
115129 NATIVESCRIPTEXCEPTION_CLASS = env.FindClass (" com/tns/NativeScriptException" );
116130 assert (NATIVESCRIPTEXCEPTION_CLASS != nullptr );
117131
118- NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID = env.GetMethodID (NATIVESCRIPTEXCEPTION_CLASS, " <init>" , " (Ljava/lang/String;J)V" );
132+ NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID = env.GetMethodID (NATIVESCRIPTEXCEPTION_CLASS, " <init>" , " (Ljava/lang/String;Ljava/lang/String; J)V" );
119133 assert (NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID != nullptr );
120134
121- NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID = env.GetMethodID (NATIVESCRIPTEXCEPTION_CLASS, " <init>" , " (Ljava/lang/String;Ljava/lang/Throwable;)V" );
135+ NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID = env.GetMethodID (NATIVESCRIPTEXCEPTION_CLASS, " <init>" , " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/ Throwable;)V" );
122136 assert (NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID != nullptr );
123137
124138 NATIVESCRIPTEXCEPTION_GET_STACK_TRACE_AS_STRING_METHOD_ID = env.GetStaticMethodID (NATIVESCRIPTEXCEPTION_CLASS, " getStackTraceAsString" , " (Ljava/lang/Throwable;)Ljava/lang/String;" );
@@ -128,8 +142,9 @@ void NativeScriptException::Init() {
128142// ON V8 UNCAUGHT EXCEPTION
129143void NativeScriptException::OnUncaughtError (Local<Message> message, Local<Value> error) {
130144 string errorMessage = GetErrorMessage (message, error);
145+ string stackTrace = GetErrorStackTrace (message->GetStackTrace ());
131146
132- NativeScriptException e (errorMessage);
147+ NativeScriptException e (errorMessage, stackTrace );
133148 e.ReThrowToJava ();
134149}
135150
@@ -203,17 +218,31 @@ Local<Value> NativeScriptException::GetJavaExceptionFromEnv(const JniLocalRef& e
203218 return errObj;
204219}
205220
206- string NativeScriptException::GetFullMessage (const TryCatch& tc, bool isExceptionEmpty, bool isMessageEmpty, const string& prependMessage ) {
221+ string NativeScriptException::GetFullMessage (const TryCatch& tc, const string& jsExceptionMessage ) {
207222 auto ex = tc.Exception ();
208223
209- string jsExeptionMessage;
224+ v8::Isolate* isolate = v8::Isolate::GetCurrent ();
225+ v8::Local<v8::Context> context = isolate->GetEnteredContext ();
210226
211- if (!isExceptionEmpty && !isMessageEmpty) {
212- jsExeptionMessage = GetErrorMessage (tc.Message (), ex);
213- }
227+ auto message = tc.Message ();
214228
215229 stringstream ss;
216- ss << endl << prependMessage << jsExeptionMessage;
230+ ss << jsExceptionMessage;
231+
232+ // get script name
233+ auto scriptResName = message->GetScriptResourceName ();
234+
235+ // get stack trace
236+ string stackTraceMessage = GetErrorStackTrace (message->GetStackTrace ());
237+
238+ if (!scriptResName.IsEmpty () && scriptResName->IsString ()) {
239+ ss << endl <<" File: \" " << ArgConverter::ConvertToString (scriptResName.As <String>());
240+ } else {
241+ ss << endl <<" File: \" <unknown>" ;
242+ }
243+ ss << " , line: " << message->GetLineNumber (context).ToChecked () << " , column: " << message->GetStartColumn () << endl << endl;
244+ ss << " StackTrace: " << endl << stackTraceMessage << endl;
245+
217246 string loggedMessage = ss.str ();
218247
219248 PrintErrorMessage (loggedMessage);
@@ -266,46 +295,38 @@ void NativeScriptException::PrintErrorMessage(const string& errorMessage) {
266295 }
267296}
268297
269- string NativeScriptException::GetErrorMessage (const Local<Message>& message, Local<Value>& error) {
298+ string NativeScriptException::GetErrorMessage (const Local<Message>& message, Local<Value>& error, const string& prependMessage ) {
270299
271300 Local<String> message_text_string = message->Get ();
272301 auto mes = ArgConverter::ConvertToString (message_text_string);
273302
274303 v8::Isolate* isolate = v8::Isolate::GetCurrent ();
275304 v8::Local<v8::Context> context = isolate->GetEnteredContext ();
276- int line_number = message->GetLineNumber (context).FromMaybe (0 );
277305
278306 // get whole error message from previous stack
307+ stringstream ss;
308+
309+ if (prependMessage != " " ) {
310+ ss << prependMessage << endl;
311+ }
312+
279313 string errMessage;
314+ bool hasFullErrorMessage = false ;
280315 auto v8FullMessage = ArgConverter::ConvertToV8String (isolate, " fullMessage" );
281316 if (error->IsObject () && error.As <Object>()->Has (context, v8FullMessage).ToChecked ()) {
317+ hasFullErrorMessage = true ;
282318 errMessage = ArgConverter::ConvertToString (error.As <Object>()->Get (v8FullMessage).As <String>());
319+ ss << errMessage;
283320 }
284321
285-
286- // get current message
287322 auto str = error->ToDetailString (context);
288- if (str.IsEmpty ()) {
289- str = String::NewFromUtf8 (isolate, " " );
290- }
291- String::Utf8Value utfError (isolate, str.FromMaybe (Local<String>()));
292-
293- // get script name
294- auto scriptResName = message->GetScriptResourceName ();
295-
296- // get stack trace
297- string stackTraceMessage = GetErrorStackTrace (message->GetStackTrace ());
298-
299- stringstream ss;
300- ss << endl << errMessage;
301- ss << endl << *utfError << endl;
302- if (!scriptResName.IsEmpty () && scriptResName->IsString ()) {
303- ss << " File: \" " << ArgConverter::ConvertToString (scriptResName.As <String>());
304- } else {
305- ss << " File: \" <unknown>" ;
323+ if (!str.IsEmpty ()) {
324+ String::Utf8Value utfError (isolate, str.FromMaybe (Local<String>()));
325+ if (hasFullErrorMessage) {
326+ ss << endl;
327+ }
328+ ss << *utfError;
306329 }
307- ss << " , line: " << message->GetLineNumber (context).ToChecked () << " , column: " << message->GetStartColumn () << endl << endl;
308- ss << " StackTrace: " << endl << stackTraceMessage << endl;
309330
310331 return ss.str ();
311332}
0 commit comments