changeset 3773:9b21f61edda7

RT-28953 - JSException should conserve the original exception
author Per Bothner <Per.Bothner@Oracle.COM>
date Thu, 30 May 2013 13:03:04 -0700
parents b17e961ecd38
children 18da8c32f363
files javafx-ui-common/src/com/sun/webkit/dom/JSObject.java webview/native/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp webview/native/Source/WebCore/platform/java/BridgeUtils.cpp webview/test/javafx/scene/web/JavaScriptBridgeTest.java
diffstat 4 files changed, 55 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-common/src/com/sun/webkit/dom/JSObject.java	Thu May 30 16:54:41 2013 +0200
+++ b/javafx-ui-common/src/com/sun/webkit/dom/JSObject.java	Thu May 30 13:03:04 2013 -0700
@@ -119,4 +119,15 @@
     public int hashCode() {
         return (int) (peer ^ (peer >> 17));
     }
+
+    private static JSException fwkMakeException(Object value) {
+        String msg = value == null ? null : value.toString();
+        // Would like to set wrappedException, but can't do that while
+        // also setting the message.  Perhaps we should create a subclass.
+        JSException ex
+            = new JSException(value == null ? null : value.toString());
+        if (value instanceof Throwable)
+            ex.initCause((Throwable) value);
+        return ex;
+    }
 }
--- a/webview/native/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp	Thu May 30 16:54:41 2013 +0200
+++ b/webview/native/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp	Thu May 30 13:03:04 2013 -0700
@@ -261,8 +261,7 @@
           JSValue exceptionDescription
             = (JavaInstance::create(ex, rootObject, accessControlContext())
                ->createRuntimeObject(exec));
-          throwError(exec, createError(exec,
-                                       exceptionDescription.toString(exec)->value(exec)));
+          throwError(exec, exceptionDescription);
           return jsUndefined();
         }
     }
--- a/webview/native/Source/WebCore/platform/java/BridgeUtils.cpp	Thu May 30 16:54:41 2013 +0200
+++ b/webview/native/Source/WebCore/platform/java/BridgeUtils.cpp	Thu May 30 13:03:04 2013 -0700
@@ -202,20 +202,19 @@
 static void throwJavaException(
     JNIEnv* env,
     JSContextRef ctx,
-    JSValueRef exception)
+    JSValueRef exception,
+    JSC::Bindings::RootObject* rootObject)
 {
-    jclass clJSException = getJSExceptionClass(env);
-    static jmethodID constructorID =
-        env->GetMethodID(clJSException, "<init>",
-                        "(Ljava/lang/String;)V");
+    jclass clJSObject = getJSObjectClass(env);
+    jobject jex = JSValue_to_Java_Object(exception, env, ctx, rootObject);
+    static jmethodID makeID =
+        env->GetStaticMethodID(clJSObject, "fwkMakeException",
+                        "(Ljava/lang/Object;)Lnetscape/javascript/JSException;");
 
-    env->Throw(JLocalRef<jthrowable>((jthrowable)env->NewObject(
-            clJSException,
-            constructorID,
-            (jstring)JLString(WebCore::JSValue_to_Java_String(
-                exception,
-                env,
-                ctx)))));
+    env->Throw(JLocalRef<jthrowable>((jthrowable)env->CallStaticObjectMethod(
+            clJSObject,
+            makeID,
+            jex)));
 }
 
 jobject executeScript(
@@ -234,7 +233,7 @@
     JSValueRef value = JSEvaluateScript(ctx, script, object, NULL, 1, &exception);
     JSStringRelease(script);
     if (exception) {
-        throwJavaException(env, ctx, exception);
+        throwJavaException(env, ctx, exception, rootObject);
         return NULL;
     }
     return WebCore::JSValue_to_Java_Object(value, env, ctx, rootObject);
@@ -340,7 +339,7 @@
     JSObjectSetProperty(ctx, object, name, jsvalue, attributes, &exception);
     JSStringRelease(name);
     if (exception)
-        WebCore::throwJavaException(env, ctx, exception);
+        WebCore::throwJavaException(env, ctx, exception, rootObject.get());
 }
 
 JNIEXPORT void JNICALL Java_com_sun_webkit_dom_JSObject_removeMemberImpl
@@ -427,7 +426,7 @@
                                                &exception);
     delete[] arguments;
     if (exception) {
-        WebCore::throwJavaException(env, ctx, exception);
+        WebCore::throwJavaException(env, ctx, exception, rootObject.get());
         return NULL;
     }
     return WebCore::JSValue_to_Java_Object(result, env, ctx, rootObject.get());
--- a/webview/test/javafx/scene/web/JavaScriptBridgeTest.java	Thu May 30 16:54:41 2013 +0200
+++ b/webview/test/javafx/scene/web/JavaScriptBridgeTest.java	Thu May 30 13:03:04 2013 -0700
@@ -259,7 +259,7 @@
             }
         }});
     }
-                
+
     public static class Carry {
         public float a;
         public double b;
@@ -352,6 +352,34 @@
         executeShouldFail(web, expression, "'undefined' is not a function");
     }
 
+    public @Test void testThrowJava() throws InterruptedException {
+        final WebEngine web = getEngine();
+
+        submit(new Runnable() { public void run() {
+            MyExceptionHelper test = new MyExceptionHelper();
+            bind("test", test);
+            try {
+                web.executeScript("test.throwException()");
+                fail("JSException expected but not thrown");
+            } catch (JSException e) {
+                assertEquals("netscape.javascript.JSException",
+                             e.getClass().getName());
+                assertTrue(e.getCause() != null);
+                assertTrue(e.getCause() instanceof MyException);
+            }
+        }});
+    }
+
+    public static class MyException extends Throwable {
+    }
+
+    public static class MyExceptionHelper {
+        public void throwException() throws MyException {
+            throw new MyException();
+        }
+    }
+
+
     public @Test void testBridgeArray1() throws InterruptedException {
         final WebEngine web = getEngine();