From 987f8b8f0045c7d924672d7514cb61cd08e6e827 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Sat, 25 Nov 2023 14:18:46 +0200 Subject: [PATCH] fix: handle native errors properly-ish --- .../interop/NativeWrapperProvider.java | 37 ++++++++++++++----- .../jscript/interop/OverloadFunction.java | 10 ++++- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/me/topchetoeu/jscript/interop/NativeWrapperProvider.java b/src/me/topchetoeu/jscript/interop/NativeWrapperProvider.java index 11f7a61..6edc93f 100644 --- a/src/me/topchetoeu/jscript/interop/NativeWrapperProvider.java +++ b/src/me/topchetoeu/jscript/interop/NativeWrapperProvider.java @@ -108,6 +108,12 @@ public class NativeWrapperProvider implements WrappersProvider { } } + public static String getName(Class clazz) { + var classNat = clazz.getAnnotation(Native.class); + if (classNat != null && !classNat.value().trim().equals("")) return classNat.value().trim(); + else return clazz.getSimpleName(); + } + /** * Generates a prototype for the given class. * The returned object will have appropriate wrappers for all instance members. @@ -117,10 +123,7 @@ public class NativeWrapperProvider implements WrappersProvider { public static ObjectValue makeProto(Environment ctx, Class clazz) { var res = new ObjectValue(); - var name = clazz.getName(); - var classNat = clazz.getAnnotation(Native.class); - if (classNat != null && !classNat.value().trim().equals("")) name = classNat.value().trim(); - res.defineProperty(null, ctx.symbol("Symbol.typeName"), name); + res.defineProperty(null, ctx.symbol("Symbol.typeName"), getName(clazz)); for (var overload : clazz.getDeclaredMethods()) { var init = overload.getAnnotation(NativeInit.class); @@ -142,11 +145,7 @@ public class NativeWrapperProvider implements WrappersProvider { * @param clazz The class for which a constructor should be generated */ public static FunctionValue makeConstructor(Environment ctx, Class clazz) { - var name = clazz.getName(); - var classNat = clazz.getAnnotation(Native.class); - if (classNat != null && !classNat.value().trim().equals("")) name = classNat.value().trim(); - - FunctionValue func = new OverloadFunction(name); + FunctionValue func = new OverloadFunction(getName(clazz)); for (var overload : clazz.getDeclaredConstructors()) { var nat = overload.getAnnotation(Native.class); @@ -261,7 +260,27 @@ public class NativeWrapperProvider implements WrappersProvider { constructors.put(clazz, value); } + private void initError() { + var proto = new ObjectValue(); + proto.defineProperty(null, "message", new NativeFunction("message", (ctx, thisArg, args) -> { + if (thisArg instanceof Throwable) return ((Throwable)thisArg).getMessage(); + else return null; + })); + proto.defineProperty(null, "name", new NativeFunction("name", (ctx, thisArg, args) -> getName(thisArg.getClass()))); + + var constr = makeConstructor(null, Throwable.class); + proto.defineProperty(null, "constructor", constr, true, false, false); + constr.defineProperty(null, "prototype", proto, true, false, false); + + proto.setPrototype(null, getProto(Object.class)); + constr.setPrototype(null, getConstr(Object.class)); + + setProto(Throwable.class, proto); + setConstr(Throwable.class, constr); + } + public NativeWrapperProvider(Environment env) { this.env = env; + initError(); } } diff --git a/src/me/topchetoeu/jscript/interop/OverloadFunction.java b/src/me/topchetoeu/jscript/interop/OverloadFunction.java index ee0470a..9edd2a5 100644 --- a/src/me/topchetoeu/jscript/interop/OverloadFunction.java +++ b/src/me/topchetoeu/jscript/interop/OverloadFunction.java @@ -8,6 +8,7 @@ import java.util.List; import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.values.FunctionValue; +import me.topchetoeu.jscript.engine.values.NativeWrapper; import me.topchetoeu.jscript.engine.values.Values; import me.topchetoeu.jscript.exceptions.ConvertException; import me.topchetoeu.jscript.exceptions.EngineException; @@ -92,7 +93,14 @@ public class OverloadFunction extends FunctionValue { throw new InterruptException(); } else { - throw EngineException.ofError(e.getTargetException().getMessage()).add(name, loc); + var target = e.getTargetException(); + var targetClass = target.getClass(); + var err = new NativeWrapper(e.getTargetException()); + + err.defineProperty(ctx, "message", target.getMessage()); + err.defineProperty(ctx, "name", NativeWrapperProvider.getName(targetClass)); + + throw new EngineException(err).add(name, loc); } } catch (ReflectiveOperationException e) {