From e584b07f01915e9b138ee22baec22c7cb40db81b Mon Sep 17 00:00:00 2001 From: "nboyd%atg.com" Date: Wed, 13 Mar 2002 13:33:40 +0000 Subject: [PATCH] Fix problem reported in newsgroup: If I have a Java class with a normal method that throws an exception, Rhino (1.5pre4) will let JavaScript catch the exception. If the Java class has a getter method, Rhino will NOT let JavaScript catch the exception. Very disturbing. Here's a console dump to show you what I'm talking about: D:\jsSandbox>cat GIJoe.java public class GIJoe { // Getter public static int getYoJoe() throws Exception { throw new Exception("Please catch me!"); } // Normal public static int rebel() throws Exception { throw new Exception("Please catch me too!"); } } D:\jsSandbox>javac GIJoe.java D:\jsSandbox>cat gi.js var gi = new Packages.GIJoe(); try { var i = gi.rebel(); java.lang.System.err.println("rebel(): uncaught"); } catch(e1) { java.lang.System.err.println("rebel(): caught"); } try { var i = gi.yoJoe; java.lang.System.err.println("yoJoe: uncaught"); } catch(e2) { java.lang.System.err.println("yoJoe: caught"); } D:\jsSandbox>java -cp .;e:\javas\rhino1_5R4pre\js.jar org.mozilla.javascript.too ls.shell.Main js> load("gi.js"); rebel(): caught java.lang.Exception: Please catch me! org.mozilla.javascript.WrappedException: WrappedException of Please catch me! at org.mozilla.javascript.JavaMembers.get(JavaMembers.java:105) at org.mozilla.javascript.NativeJavaObject.get(NativeJavaObject.java:93) at org.mozilla.javascript.ScriptRuntime.getProp(ScriptRuntime.java:691) at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:1591) at org.mozilla.javascript.InterpretedScript.call(InterpretedScript.java: 63) at org.mozilla.javascript.InterpretedScript.exec(InterpretedScript.java: 54) at org.mozilla.javascript.Context.evaluateReader(Context.java:741) at org.mozilla.javascript.tools.shell.Main.evaluateReader(Main.java:347) at org.mozilla.javascript.tools.shell.Main.processSource(Main.java:336) at org.mozilla.javascript.tools.shell.Global.load(Global.java:169) at java.lang.reflect.Method.invoke(Native Method) at org.mozilla.javascript.FunctionObject.callVarargs(FunctionObject.java :586) at org.mozilla.javascript.FunctionObject.call(FunctionObject.java:460) at org.mozilla.javascript.ScriptRuntime.call(ScriptRuntime.java:1216) at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:1679) at org.mozilla.javascript.InterpretedScript.call(InterpretedScript.java: 63) at org.mozilla.javascript.InterpretedScript.exec(InterpretedScript.java: 54) at org.mozilla.javascript.Context.evaluateReader(Context.java:741) at org.mozilla.javascript.tools.shell.Main.evaluateReader(Main.java:347) at org.mozilla.javascript.tools.shell.Main.processSource(Main.java:284) at org.mozilla.javascript.tools.shell.Main.exec(Main.java:146) at org.mozilla.javascript.tools.shell.Main.main(Main.java:74) js> Due to a lack of an "uncaught" statement in the output, we see that the exception from GIJoe::getYoJoe() was indeed thrown, but not caught by the JavaScript. Do any nightly builds past 1.5pre4 address this issue? Todd Trimmer --- .../org/mozilla/javascript/Interpreter.java | 48 ++++++++++++------- .../org/mozilla/javascript/JavaMembers.java | 2 + 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/js/rhino/src/org/mozilla/javascript/Interpreter.java b/js/rhino/src/org/mozilla/javascript/Interpreter.java index 07ef9bf8fbda..98a396780dbf 100644 --- a/js/rhino/src/org/mozilla/javascript/Interpreter.java +++ b/js/rhino/src/org/mozilla/javascript/Interpreter.java @@ -2211,26 +2211,38 @@ public class Interpreter extends LabelTable { } final int SCRIPT_THROW = 0, ECMA = 1, RUNTIME = 2, OTHER = 3; - int exType; Object errObj; // Object seen by catch - if (ex instanceof JavaScriptException) { - errObj = ScriptRuntime. - unwrapJavaScriptException((JavaScriptException)ex); - exType = SCRIPT_THROW; - } - else if (ex instanceof EcmaError) { - // an offical ECMA error object, - errObj = ((EcmaError)ex).getErrorObject(); - exType = ECMA; - } - else if (ex instanceof RuntimeException) { - errObj = ex; - exType = RUNTIME; - } - else { - errObj = ex; // Error instance - exType = OTHER; + + for (;;) { + if (ex instanceof JavaScriptException) { + errObj = ScriptRuntime. + unwrapJavaScriptException((JavaScriptException)ex); + exType = SCRIPT_THROW; + } + else if (ex instanceof EcmaError) { + // an offical ECMA error object, + errObj = ((EcmaError)ex).getErrorObject(); + exType = ECMA; + } + else if (ex instanceof WrappedException) { + Object w = ((WrappedException) ex).unwrap(); + if (w instanceof Throwable) { + ex = (Throwable) w; + continue; + } + errObj = ex; + exType = RUNTIME; + } + else if (ex instanceof RuntimeException) { + errObj = ex; + exType = RUNTIME; + } + else { + errObj = ex; // Error instance + exType = OTHER; + } + break; } if (exType != OTHER && cx.debugger != null) { diff --git a/js/rhino/src/org/mozilla/javascript/JavaMembers.java b/js/rhino/src/org/mozilla/javascript/JavaMembers.java index effc178c1330..5799435a88ee 100644 --- a/js/rhino/src/org/mozilla/javascript/JavaMembers.java +++ b/js/rhino/src/org/mozilla/javascript/JavaMembers.java @@ -110,6 +110,8 @@ class JavaMembers { throw new RuntimeException("unexpected IllegalAccessException "+ "accessing Java field"); } catch (InvocationTargetException e) { + // Since JavaScriptException is a checked exception, must + // wrap the JavaScriptException in a WrappedException throw WrappedException.wrapException( JavaScriptException.wrapException(scope, e)); }