JS: display Java exception message in uncaught exceptions in console

This commit is contained in:
Alexey Andreev 2023-03-02 20:21:41 +01:00
parent 07d56f1b0b
commit 0f8d36a080
3 changed files with 52 additions and 1 deletions

View File

@ -295,6 +295,9 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
includeStackTraceMethods(dependencyAnalyzer); includeStackTraceMethods(dependencyAnalyzer);
} }
dependencyAnalyzer.linkMethod(new MethodReference(Throwable.class, "getMessage", String.class)).use();
dependencyAnalyzer.linkMethod(new MethodReference(Throwable.class, "getCause", Throwable.class)).use();
dependencyAnalyzer.addDependencyListener(new AbstractDependencyListener() { dependencyAnalyzer.addDependencyListener(new AbstractDependencyListener() {
@Override @Override
public void methodReached(DependencyAgent agent, MethodDependency method) { public void methodReached(DependencyAgent agent, MethodDependency method) {

View File

@ -70,6 +70,7 @@ public class RuntimeRenderer {
renderRuntimeUnwrapString(); renderRuntimeUnwrapString();
renderRuntimeObjcls(); renderRuntimeObjcls();
renderRuntimeThrowablecls(); renderRuntimeThrowablecls();
renderRuntimeThrowableMethods();
renderRuntimeNullCheck(); renderRuntimeNullCheck();
renderRuntimeIntern(); renderRuntimeIntern();
renderRuntimeThreads(); renderRuntimeThreads();
@ -203,6 +204,18 @@ public class RuntimeRenderer {
writer.append(";").softNewLine().outdent().append("}").newLine(); writer.append(";").softNewLine().outdent().append("}").newLine();
} }
private void renderRuntimeThrowableMethods() throws IOException {
writer.append("function $rt_throwableMessage(t)").ws().append("{").indent().softNewLine();
writer.append("return ");
writer.appendMethodBody(Throwable.class, "getMessage", String.class).append("(t);").softNewLine();
writer.outdent().append("}").newLine();
writer.append("function $rt_throwableCause(t)").ws().append("{").indent().softNewLine();
writer.append("return ");
writer.appendMethodBody(Throwable.class, "getCause", Throwable.class).append("(t);").softNewLine();
writer.outdent().append("}").newLine();
}
private void renderRuntimeThreads() throws IOException { private void renderRuntimeThreads() throws IOException {
ClassReader threadCls = classSource.get(THREAD_CLASS); ClassReader threadCls = classSource.get(THREAD_CLASS);
MethodReader currentThreadMethod = threadCls != null ? threadCls.getMethod(CURRENT_THREAD_METHOD) : null; MethodReader currentThreadMethod = threadCls != null ? threadCls.getMethod(CURRENT_THREAD_METHOD) : null;

View File

@ -284,7 +284,10 @@ var $rt_javaExceptionProp = Symbol("javaException")
function $rt_exception(ex) { function $rt_exception(ex) {
var err = ex.$jsException; var err = ex.$jsException;
if (!err) { if (!err) {
err = new Error("Java exception thrown"); var javaCause = $rt_throwableCause(ex);
var jsCause = javaCause !== null ? javaCause.$jsException : undefined;
var cause = typeof jsCause === "object" ? { cause : jsCause } : undefined;
err = new JavaError("Java exception thrown", cause);
if (typeof Error.captureStackTrace === "function") { if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(err); Error.captureStackTrace(err);
} }
@ -694,6 +697,38 @@ function $rt_intBitsToFloat(n) {
return $rt_numberConversionView.getFloat32(0); return $rt_numberConversionView.getFloat32(0);
} }
var JavaError;
if (typeof Reflect === 'object') {
var defaultMessage = Symbol("defaultMessage");
JavaError = function JavaError(message, cause) {
var self = Reflect.construct(Error, [undefined, cause], JavaError);
Object.setPrototypeOf(self, JavaError.prototype);
self[defaultMessage] = message;
return self;
}
JavaError.prototype = Object.create(Error.prototype, {
constructor: {
configurable: true,
writable: true,
value: JavaError
},
message: {
get: function() {
var javaException = this[$rt_javaExceptionProp];
if (typeof javaException === 'object') {
var javaMessage = $rt_throwableMessage(javaException);
if (typeof javaMessage === "object") {
return javaMessage.toString();
}
}
return this[defaultMessage];
}
}
});
} else {
JavaError = Error;
}
function $rt_javaException(e) { function $rt_javaException(e) {
return e instanceof Error && typeof e[$rt_javaExceptionProp] === 'object' ? e[$rt_javaExceptionProp] : null; return e instanceof Error && typeof e[$rt_javaExceptionProp] === 'object' ? e[$rt_javaExceptionProp] : null;
} }