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();