Skip to content

Commit f147b7c

Browse files
committed
Merge branch 'plamen5kov/nativescript_exception_fix' into release
1 parent 2de6c6f commit f147b7c

File tree

4 files changed

+95
-29
lines changed

4 files changed

+95
-29
lines changed

runtime/src/main/jni/NativeScriptException.cpp

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,7 @@ void NativeScriptException::Init(ObjectManager *objectManager)
155155
// ON V8 UNCAUGHT EXCEPTION
156156
void NativeScriptException::OnUncaughtError(Local<Message> message, Local<Value> error)
157157
{
158-
auto isolate = Isolate::GetCurrent();
159-
string errorMessage;
160-
auto v8FullMessage = ArgConverter::ConvertToV8String(isolate, "fullMessage");
161-
162-
if(error->IsObject() && error.As<Object>()->Has(v8FullMessage)) {
163-
errorMessage = ArgConverter::ConvertToString(error.As<Object>()->Get(v8FullMessage).As<String>());
164-
}
165-
166-
if(errorMessage.size() == 0) {
167-
errorMessage = GetErrorMessage(message, error);
168-
}
158+
string errorMessage = GetErrorMessage(message, error);
169159

170160
NativeScriptException e(errorMessage);
171161
e.ReThrowToJava();
@@ -252,17 +242,18 @@ string NativeScriptException::GetFullMessage(const TryCatch& tc, bool isExceptio
252242
{
253243
auto ex = tc.Exception();
254244

255-
string message;
245+
string jsExeptionMessage;
246+
256247
if (!isExceptionEmpty && !isMessageEmpty)
257248
{
258-
message = PrintErrorMessage(tc.Message(), ex);
249+
jsExeptionMessage = GetErrorMessage(tc.Message(), ex);
259250
}
260251

261252
stringstream ss;
262-
ss << endl << prependMessage << message;
253+
ss << endl << prependMessage << jsExeptionMessage;
263254
string loggedMessage = ss.str();
264255

265-
DEBUG_WRITE("Error: %s", loggedMessage.c_str());
256+
PrintErrorMessage(loggedMessage);
266257

267258
if (!tc.CanContinue())
268259
{
@@ -306,10 +297,7 @@ JniLocalRef NativeScriptException::TryGetJavaThrowableObject(JEnv& env, const Lo
306297
return javaThrowableObject;
307298
}
308299

309-
string NativeScriptException::PrintErrorMessage(const Local<Message>& message, const Local<Value>& error)
310-
{
311-
string errorMessage = GetErrorMessage(message, error);
312-
300+
void NativeScriptException::PrintErrorMessage(const string &errorMessage) {
313301
// split the message by new lines to workaround the LogCat's maximum characters in a single message
314302
stringstream ss(errorMessage);
315303
string line;
@@ -318,22 +306,34 @@ string NativeScriptException::PrintErrorMessage(const Local<Message>& message, c
318306
// TODO: Log in the V8's Console as well?
319307
DEBUG_WRITE("%s", line.c_str());
320308
}
321-
322-
return errorMessage;
323309
}
324310

325-
string NativeScriptException::GetErrorMessage(const Local<Message>& message, const Local<Value>& error)
311+
string NativeScriptException::GetErrorMessage(const Local<Message>& message, Local<Value>& error)
326312
{
327-
stringstream ss;
313+
//get whole error message from previous stack
314+
string errMessage;
315+
auto v8FullMessage = ArgConverter::ConvertToV8String(Isolate::GetCurrent(), "fullMessage");
316+
if(error->IsObject() && error.As<Object>()->Has(v8FullMessage)) {
317+
errMessage = ArgConverter::ConvertToString(error.As<Object>()->Get(v8FullMessage).As<String>());
318+
}
328319

320+
//get current message
329321
auto str = error->ToDetailString();
330322
if (str.IsEmpty())
331323
{
332324
str = String::NewFromUtf8(Isolate::GetCurrent(), "");
333325
}
334326
String::Utf8Value utfError(str);
335-
ss << endl << endl << *utfError << endl;
327+
328+
//get script name
336329
auto scriptResName = message->GetScriptResourceName();
330+
331+
//get stack trace
332+
string stackTraceMessage = GetErrorStackTrace(message->GetStackTrace());
333+
334+
stringstream ss;
335+
ss << endl << errMessage;
336+
ss << endl << *utfError << endl;
337337
if (!scriptResName.IsEmpty() && scriptResName->IsString())
338338
{
339339
ss << "File: \"" << ArgConverter::ConvertToString(scriptResName.As<String>());
@@ -342,10 +342,7 @@ string NativeScriptException::GetErrorMessage(const Local<Message>& message, con
342342
{
343343
ss << "File: \"<unknown>";
344344
}
345-
346345
ss << ", line: " << message->GetLineNumber() << ", column: " << message->GetStartColumn() << endl << endl;
347-
348-
string stackTraceMessage = GetErrorStackTrace(message->GetStackTrace());
349346
ss << "StackTrace: " << endl << stackTraceMessage << endl;
350347

351348
return ss.str();

runtime/src/main/jni/NativeScriptException.h

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,70 @@ namespace tns
1111
class NativeScriptException
1212
{
1313
public:
14+
/*
15+
* Generates a NativeScriptException with java error from environment
16+
*/
1417
NativeScriptException(JEnv& env);
18+
19+
/*
20+
* Generates a NativeScriptException with given message
21+
*/
1522
NativeScriptException(const std::string& message);
23+
24+
/*
25+
* Generates a NativeScriptException with javascript error from TryCatch and a prepend message if any
26+
*/
1627
NativeScriptException(v8::TryCatch& tc, const std::string& message = "");
1728

1829
void ReThrowToV8();
1930
void ReThrowToJava();
2031

2132
static void Init(ObjectManager *objectManager);
33+
34+
/*
35+
* This handler is attached to v8 to handle uncaught javascript exceptions.
36+
*/
2237
static void OnUncaughtError(v8::Local<v8::Message> message, v8::Local<v8::Value> error);
38+
39+
/*
40+
* Calls the global "__onUncaughtError" if such is provided
41+
*/
2342
static void CallJsFuncWithErr(v8::Local<v8::Value> errObj);
2443

2544
private:
45+
/*
46+
* Try to get native exception or NativeScriptException from js object
47+
*/
2648
JniLocalRef TryGetJavaThrowableObject(JEnv& env, const v8::Local<v8::Object>& jsObj);
49+
50+
/*
51+
* Gets java exception stack message from jthrowable
52+
*/
2753
std::string GetExceptionMessage(JEnv& env, jthrowable exception);
54+
55+
/*
56+
* Gets the member m_javaException, wraps it and creates a javascript error object from it
57+
*/
2858
v8::Local<v8::Value> WrapJavaToJsException();
59+
60+
/*
61+
* Gets all the information from a java exception and puts it in a javascript errror object
62+
*/
2963
v8::Local<v8::Value> GetJavaExceptionFromEnv(const JniLocalRef& exc, JEnv& env);
30-
static std::string PrintErrorMessage(const v8::Local<v8::Message>& message, const v8::Local<v8::Value>& error);
31-
static std::string GetErrorMessage(const v8::Local<v8::Message>& message, const v8::Local<v8::Value>& error);
64+
65+
/*
66+
* Gets all the information from a js message and an js error object and puts it in a string
67+
*/
68+
static std::string GetErrorMessage(const v8::Local<v8::Message>& message, v8::Local<v8::Value>& error);
69+
70+
/*
71+
* Generates string stack trace from js StackTrace
72+
*/
3273
static std::string GetErrorStackTrace(const v8::Local<v8::StackTrace>& stackTrace);
3374

75+
/*
76+
* Adds a prepend message to the normal message process
77+
*/
3478
std::string GetFullMessage(const v8::TryCatch& tc, bool isExceptionEmpty, bool isMessageEmpty, const std::string& prependMessage = "");
3579

3680
v8::Persistent<v8::Value> *m_javascriptException;
@@ -44,6 +88,8 @@ namespace tns
4488
static jmethodID NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID;
4589
static jmethodID NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID;
4690
static jmethodID NATIVESCRIPTEXCEPTION_GET_STACK_TRACE_AS_STRING_METHOD_ID;
91+
92+
static void PrintErrorMessage(const std::string &errorMessage);
4793
};
4894
}
4995

test-app/app/src/main/assets/app/tests/exceptionHandlingTests.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,23 @@ describe("Tests exception handling ", function () {
323323
expect(exceptionCaught).toBe(true);
324324
expect(errMsg).toBe("Error: Unknown error. Cannot get error message.");
325325
});
326+
327+
it("should successfully catch syntax errors", function () {
328+
329+
var exceptionCaught = false;
330+
var errMsg;
331+
try {
332+
require("./syntaxErrors.js");
333+
} catch (e) {
334+
exceptionCaught = true;
335+
errMsg = e.fullMessage
336+
}
337+
expect(exceptionCaught).toBe(true);
338+
expect(errMsg).toContain("Cannot compile /data/data/com.tns.android_runtime_testapp/files/app/tests/syntaxErrors.js");
339+
expect(errMsg).toContain("SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode");
340+
expect(errMsg).toContain("File: \"/data/data/com.tns.android_runtime_testapp/files/app/tests/syntaxErrors.js, line: 4, column: 0");
341+
342+
343+
344+
});
326345
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//this file is required
2+
3+
var b = 5;
4+
let a = 5;

0 commit comments

Comments
 (0)