Fixes missing unwrapping logic in emulated stack mode.
This was causing JavaScript errors to propagate as wrapped
object incorrectly.
Change-Id: I79143f7683c31bb2e5d117bba9c0ecf6eaea2aa4
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java b/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
index bb7f1ff..0faa7ad 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
@@ -458,7 +458,7 @@
private JsCatch makeSyntheticCatchBlock(JsTry x) {
/*
- * catch (e) { e = wrap(e); throw e; }
+ * catch (e) { e = wrap(e); throw unwrap(e); }
*/
SourceInfo info = x.getSourceInfo();
@@ -473,8 +473,12 @@
JsBinaryOperation asg = new JsBinaryOperation(info, JsBinaryOperator.ASG,
paramName.makeRef(info), wrapCall);
- // throw e
- JsThrow throwStatement = new JsThrow(info, paramName.makeRef(info));
+ // unwrap(e)
+ JsInvocation unwrapCall =
+ new JsInvocation(info, unwrapFunctionName.makeRef(info), paramName.makeRef(info));
+
+ // throw unwrap(e)
+ JsThrow throwStatement = new JsThrow(info, unwrapCall);
JsBlock body = new JsBlock(info);
body.getStatements().add(asg.makeStmt());
@@ -968,6 +972,7 @@
}
private JsName wrapFunctionName;
+ private JsName unwrapFunctionName;
private JsName lineNumbers;
private JProgram jprogram;
private final JsProgram jsProgram;
@@ -1008,10 +1013,13 @@
private void execImpl() {
wrapFunctionName =
JsUtils.getJsNameForMethod(jjsmap, jprogram, RuntimeConstants.EXCEPTIONS_WRAP);
+ unwrapFunctionName =
+ JsUtils.getJsNameForMethod(jjsmap, jprogram, RuntimeConstants.EXCEPTIONS_UNWRAP);
if (wrapFunctionName == null) {
// No exceptions caught? Weird, but possible.
return;
}
+ assert unwrapFunctionName != null;
initNames();
makeVars();
(new ReplaceUnobfuscatableNames()).accept(jsProgram);
diff --git a/user/test/com/google/gwt/core/client/JavaScriptExceptionTest.java b/user/test/com/google/gwt/core/client/JavaScriptExceptionTest.java
index e679535..9faa5e6 100644
--- a/user/test/com/google/gwt/core/client/JavaScriptExceptionTest.java
+++ b/user/test/com/google/gwt/core/client/JavaScriptExceptionTest.java
@@ -107,6 +107,20 @@
};
}
+ private static boolean keepFinallyAlive = false;
+
+ private static Runnable wrapWithFinally(final Runnable runnable) {
+ return new Runnable() {
+ @Override public void run() {
+ try {
+ runnable.run();
+ } finally {
+ keepFinallyAlive = true;
+ }
+ }
+ };
+ }
+
private static void assertJavaScriptException(Object expected, Throwable exception) {
assertTrue(exception instanceof JavaScriptException);
assertEquals(expected, ((JavaScriptException) exception).getThrown());
@@ -142,6 +156,17 @@
assertJavaScriptException(jso, catchJava(createThrowRunnable(e)));
}
+ public void testCatchNativePropagatedFromFinally() {
+ RuntimeException e = new RuntimeException();
+ assertSame(e, catchNative(wrapWithFinally(createThrowRunnable(e))));
+
+ JavaScriptObject jso = makeJSO();
+ e = new JavaScriptException(jso);
+ assertSame(jso, catchNative(wrapWithFinally(createThrowRunnable(e))));
+
+ assertTrue(keepFinallyAlive);
+ }
+
// java throw -> jsni catch -> jsni throw -> java catch
public void testJavaNativeJavaSandwichCatch() {
RuntimeException e = new RuntimeException();