Improves Dev Mode reporting of JavaScriptException to include method name and args. Review at http://gwt-code-reviews.appspot.com/1570803 Review by: tobyr@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10704 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java index 63ad7ea..871e6db 100644 --- a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java +++ b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
@@ -28,6 +28,7 @@ import java.net.MalformedURLException; import java.net.Socket; import java.net.URL; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -241,8 +242,8 @@ // JSException exceptionValue = returnValue.getValue().toString(); } - RuntimeException exception = ModuleSpace.createJavaScriptException( - ccl, exceptionValue); + RuntimeException exception = ModuleSpace.createJavaScriptException(ccl, + exceptionValue, methodName + "(" + Arrays.toString(args) + ")"); // reset the stack trace to here to minimize GWT infrastructure in // the stack trace exception.fillInStackTrace();
diff --git a/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java b/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java index ecb8ff6..9a11514 100644 --- a/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java +++ b/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java
@@ -55,19 +55,28 @@ } /** + * Equivalent to {@link #createJavaScriptException(ClassLoader,Object,String) + * createJavaScriptException(cl, exception, "")}. + */ + protected static RuntimeException createJavaScriptException(ClassLoader cl, + Object exception) { + return createJavaScriptException(cl, exception, ""); + } + + /** * Create a JavaScriptException object. This must be done reflectively, since * this class will have been loaded from a ClassLoader other than the * session's thread. */ protected static RuntimeException createJavaScriptException(ClassLoader cl, - Object exception) { + Object exception, String message) { Exception caught; try { Class<?> javaScriptExceptionClass = Class.forName( "com.google.gwt.core.client.JavaScriptException", true, cl); Constructor<?> ctor = javaScriptExceptionClass.getDeclaredConstructor( - Object.class); - return (RuntimeException) ctor.newInstance(new Object[] {exception}); + Object.class, String.class); + return (RuntimeException) ctor.newInstance(new Object[] {exception, message}); } catch (InstantiationException e) { caught = e; } catch (IllegalAccessException e) {
diff --git a/user/src/com/google/gwt/core/client/JavaScriptException.java b/user/src/com/google/gwt/core/client/JavaScriptException.java index 36efebc..5c44f48 100644 --- a/user/src/com/google/gwt/core/client/JavaScriptException.java +++ b/user/src/com/google/gwt/core/client/JavaScriptException.java
@@ -45,23 +45,23 @@ */ public final class JavaScriptException extends RuntimeException { - private static String getDescription(Object e) { + private static String getExceptionDescription(Object e) { if (e instanceof JavaScriptObject) { - return getDescription0((JavaScriptObject) e); + return getExceptionDescription0((JavaScriptObject) e); } else { return e + ""; } } - private static native String getDescription0(JavaScriptObject e) /*-{ + private static native String getExceptionDescription0(JavaScriptObject e) /*-{ return (e == null) ? null : e.message; }-*/; - private static String getName(Object e) { + private static String getExceptionName(Object e) { if (e == null) { return "null"; } else if (e instanceof JavaScriptObject) { - return getName0((JavaScriptObject) e); + return getExceptionName0((JavaScriptObject) e); } else if (e instanceof String) { return "String"; } else { @@ -69,11 +69,11 @@ } } - private static native String getName0(JavaScriptObject e) /*-{ + private static native String getExceptionName0(JavaScriptObject e) /*-{ return (e == null) ? null : e.name; }-*/; - private static String getProperties(Object e) { + private static String getExceptionProperties(Object e) { return (GWT.isScript() && e instanceof JavaScriptObject) ? StackTraceCreator.getProperties((JavaScriptObject) e) : ""; } @@ -82,7 +82,7 @@ * The original description of the JavaScript exception this class wraps, * initialized as <code>e.message</code>. */ - private String description; + private String description = ""; /** * The underlying exception this class wraps. @@ -104,7 +104,18 @@ * @param e the object caught in JavaScript that triggered the exception */ public JavaScriptException(Object e) { + this(e, ""); + } + + /** + * @param e the object caught in JavaScript that triggered the exception + * @param description to include in getMessage(), e.g. at the top of a stack + * trace + */ + public JavaScriptException(Object e, String description) { this.e = e; + this.description = description; + /* * In Development Mode, JavaScriptExceptions are created exactly when the * native method returns and their stack traces are fixed-up by the @@ -117,7 +128,7 @@ StackTraceCreator.createStackTrace(this); } } - + public JavaScriptException(String name, String description) { this.message = "JavaScript " + name + " exception: " + description; this.name = name; @@ -176,9 +187,9 @@ } private void init() { - name = getName(e); - description = getDescription(e); - message = "(" + name + "): " + description + getProperties(e); + name = getExceptionName(e); + description = description + ": " + getExceptionDescription(e); + message = "(" + name + ") " + getExceptionProperties(e) + description; } }
diff --git a/user/test/com/google/gwt/core/client/JavaScriptExceptionTest.java b/user/test/com/google/gwt/core/client/JavaScriptExceptionTest.java index 54d2eed..d4b193e 100644 --- a/user/test/com/google/gwt/core/client/JavaScriptExceptionTest.java +++ b/user/test/com/google/gwt/core/client/JavaScriptExceptionTest.java
@@ -62,10 +62,10 @@ fail(); } catch (JavaScriptException e) { assertEquals("myName", e.getName()); - assertEquals("myDescription", e.getDescription()); + assertDescription(e, "myDescription"); assertSame(jso, e.getException()); assertTrue(e.getMessage().contains("myName")); - assertTrue(e.getMessage().contains("myDescription")); + assertTrue(e.getMessage().contains(e.getDescription())); if (extraPropertiesShouldBePresent) { assertTrue( "message does not contain 'extraField', but should: " @@ -115,7 +115,7 @@ assertSame(e, t); } } - + @WithProperties({ @Property(name = "compiler.stackMode", value = "emulated") }) @@ -142,7 +142,7 @@ */ assertJsoProperties(GWT.isScript()); } - + @WithProperties({ @Property(name = "compiler.stackMode", value = "strip") }) @@ -163,7 +163,7 @@ fail(); } catch (JavaScriptException e) { assertEquals("null", e.getName()); - assertEquals("null", e.getDescription()); + assertDescription(e, "null"); assertEquals(null, e.getException()); assertTrue(e.getMessage().contains("null")); } @@ -181,10 +181,10 @@ fail(); } catch (JavaScriptException e) { assertEquals(o.getClass().getName(), e.getName()); - assertEquals("myLameObject", e.getDescription()); + assertDescription(e, "myLameObject"); assertEquals(null, e.getException()); assertTrue(e.getMessage().contains(o.getClass().getName())); - assertTrue(e.getMessage().contains("myLameObject")); + assertTrue(e.getMessage().contains(e.getDescription())); } } @@ -194,9 +194,20 @@ fail(); } catch (JavaScriptException e) { assertEquals("String", e.getName()); - assertEquals("foobarbaz", e.getDescription()); + assertDescription(e, "foobarbaz"); assertEquals(null, e.getException()); - assertTrue(e.getMessage().contains("foobarbaz")); + assertTrue(e.getMessage().contains(e.getDescription())); } } + + private void assertDescription(JavaScriptException e, String description) { + if (!GWT.isScript()) { + assertTrue("Should start with method name", + e.getDescription().startsWith( + "@com.google.gwt.core.client.JavaScriptExceptionTest::" + + "throwNative(Ljava/lang/Object;)")); + } + assertTrue("Should end with " + description, + e.getDescription().endsWith(description)); + } }